Пример #1
0
    def test_that_function_should_raise_exception_when_type_is_not_allowed(
            self, id_):

        with pytest.raises(ConcentValidationError) as exception:
            validate_uuid(id_)
        assert_that(exception.value.error_code).is_equal_to(
            ErrorCode.MESSAGE_WRONG_UUID_TYPE)
Пример #2
0
def claim_deposit(
    subtask_id: str,
    concent_use_case: ConcentUseCase,
    requestor_ethereum_address: str,
    provider_ethereum_address: str,
    subtask_cost: int,
    requestor_public_key: bytes,
    provider_public_key: bytes,
) -> Tuple[Optional[DepositClaim], Optional[DepositClaim]]:
    """
    The purpose of this operation is to check whether the clients participating in a use case have enough funds in their
    deposits to cover all the costs associated with the use case in the pessimistic scenario.
    """

    assert isinstance(concent_use_case, ConcentUseCase)
    assert isinstance(requestor_ethereum_address, str)
    assert isinstance(provider_ethereum_address, str)
    assert isinstance(subtask_cost, int) and subtask_cost > 0

    assert concent_use_case in [
        ConcentUseCase.FORCED_ACCEPTANCE,
        ConcentUseCase.ADDITIONAL_VERIFICATION
    ]
    assert len(requestor_ethereum_address) == ETHEREUM_ADDRESS_LENGTH
    assert len(provider_ethereum_address) == ETHEREUM_ADDRESS_LENGTH
    assert provider_ethereum_address != requestor_ethereum_address

    validate_bytes_public_key(requestor_public_key, 'requestor_public_key')
    validate_bytes_public_key(provider_public_key, 'provider_public_key')
    validate_uuid(subtask_id)

    is_claim_against_provider: bool = (
        concent_use_case == ConcentUseCase.ADDITIONAL_VERIFICATION
        and settings.ADDITIONAL_VERIFICATION_COST > 0)
    # Bankster creates Client and DepositAccount objects (if they don't exist yet) for the requestor
    # and also for the provider if there's a non-zero claim against his account.
    # This is done in single database transaction.
    requestor_client: Client = get_or_create_with_retry(
        Client, public_key=requestor_public_key)
    requestor_deposit_account: DepositAccount = get_or_create_with_retry(
        DepositAccount,
        client=requestor_client,
        ethereum_address=requestor_ethereum_address,
    )
    if is_claim_against_provider:
        provider_client: Client = get_or_create_with_retry(
            Client, public_key=provider_public_key)
        provider_deposit_account: DepositAccount = get_or_create_with_retry(
            DepositAccount,
            client=provider_client,
            ethereum_address=provider_ethereum_address,
        )

    # Bankster asks SCI about the amount of funds available in requestor's deposit.
    requestor_deposit = service.get_deposit_value(
        client_eth_address=requestor_ethereum_address)  # pylint: disable=no-value-for-parameter

    # If the amount claimed from provider's deposit is non-zero,
    # Bankster asks SCI about the amount of funds available in his deposit.
    if is_claim_against_provider:
        provider_deposit = service.get_deposit_value(
            client_eth_address=provider_ethereum_address)  # pylint: disable=no-value-for-parameter

    # Bankster puts database locks on DepositAccount objects
    # that will be used as payers in newly created DepositClaims.
    with non_nesting_atomic(using='control'):
        DepositAccount.objects.select_for_update().filter(
            client=requestor_client,
            ethereum_address=requestor_ethereum_address,
        )
        if is_claim_against_provider:
            DepositAccount.objects.select_for_update().filter(
                client=provider_client,
                ethereum_address=provider_ethereum_address,
            )

        # Bankster sums the amounts of all existing DepositClaims that have the same payer as the one being processed.
        aggregated_claims_against_requestor = DepositClaim.objects.filter(
            payer_deposit_account=requestor_deposit_account).aggregate(
                sum_of_existing_claims=Coalesce(Sum('amount'), 0))

        # If the existing claims against requestor's deposit are greater or equal to his current deposit,
        # we can't add a new claim.
        if requestor_deposit <= aggregated_claims_against_requestor[
                'sum_of_existing_claims']:
            return (None, None)

        # Deposit lock for requestor.
        claim_against_requestor = DepositClaim(
            subtask_id=subtask_id,
            payee_ethereum_address=provider_ethereum_address,
            amount=subtask_cost,
            concent_use_case=concent_use_case,
            payer_deposit_account=requestor_deposit_account,
        )
        claim_against_requestor.full_clean()
        claim_against_requestor.save()

        if is_claim_against_provider:
            # Bankster sums the amounts of all existing DepositClaims where the provider is the payer.
            aggregated_claims_against_provider = DepositClaim.objects.filter(
                payer_deposit_account=provider_deposit_account).aggregate(
                    sum_of_existing_claims=Coalesce(Sum('amount'), 0))

            # If the total of existing claims and the current claim is greater or equal to the current deposit,
            # we can't add a new claim.
            provider_obligations = aggregated_claims_against_provider[
                'sum_of_existing_claims'] + settings.ADDITIONAL_VERIFICATION_COST
            if provider_deposit <= provider_obligations:
                claim_against_requestor.delete()
                raise BanksterTooSmallProviderDepositError(
                    f'Provider deposit is {provider_deposit} (required: {provider_obligations}'
                )

        # Deposit lock for provider.
        if is_claim_against_provider:
            claim_against_provider = DepositClaim(
                subtask_id=subtask_id,
                payee_ethereum_address=ethereum_public_key_to_address(
                    settings.CONCENT_ETHEREUM_PUBLIC_KEY),
                amount=settings.ADDITIONAL_VERIFICATION_COST,
                concent_use_case=concent_use_case,
                payer_deposit_account=provider_deposit_account,
            )
            claim_against_provider.full_clean()
            claim_against_provider.save()
        else:
            claim_against_provider = None  # type: ignore

    return (claim_against_requestor, claim_against_provider)
Пример #3
0
    def test_that_function_should_pass_when_value_is_allowed(self, id_):

        try:
            validate_uuid(id_)
        except Exception as exception:  # pylint: disable=broad-except
            pytest.fail(f'{exception}')
Пример #4
0
def _hexencode_uuid(value: str) -> bytes:
    validate_uuid(value)

    return binascii.hexlify(uuid.UUID(value).bytes)
Пример #5
0
def _hexencode_uuid(value: str) -> bytes:
    validate_uuid(value)

    return uuid_to_bytes32(uuid.UUID(value))