def create_n_deposits_with_subtasks(self, n=1, amount=2): for _ in range(n): task_to_compute = self._get_deserialized_task_to_compute( provider_public_key=self._get_provider_hex_public_key(), requestor_public_key=self._get_requestor_hex_public_key(), price=amount, ) store_subtask( task_id=task_to_compute.task_id, subtask_id=task_to_compute.subtask_id, provider_public_key=self.PROVIDER_PUBLIC_KEY, requestor_public_key=self.REQUESTOR_PUBLIC_KEY, state=Subtask.SubtaskState.ACCEPTED, next_deadline=None, task_to_compute=task_to_compute, report_computed_task=factories.tasks.ReportComputedTaskFactory( task_to_compute=task_to_compute)) deposit_claim = DepositClaim() deposit_claim.subtask_id = task_to_compute.subtask_id deposit_claim.payer_deposit_account = self.deposit_account deposit_claim.payee_ethereum_address = task_to_compute.provider_ethereum_address deposit_claim.concent_use_case = ConcentUseCase.FORCED_ACCEPTANCE deposit_claim.amount = amount deposit_claim.clean() deposit_claim.save() return deposit_claim, task_to_compute
class DiscardClaimBanksterTest(ConcentIntegrationTestCase): def setUp(self): super().setUp() self.task_to_compute = self._get_deserialized_task_to_compute() self.client = Client(public_key_bytes=self.PROVIDER_PUBLIC_KEY) self.client.clean() self.client.save() self.deposit_account = DepositAccount() self.deposit_account.client = self.client self.deposit_account.ethereum_address = self.task_to_compute.requestor_ethereum_address self.deposit_account.clean() self.deposit_account.save() self.deposit_claim = DepositClaim() self.deposit_claim.payer_deposit_account = self.deposit_account self.deposit_claim.payee_ethereum_address = self.task_to_compute.provider_ethereum_address self.deposit_claim.concent_use_case = ConcentUseCase.FORCED_PAYMENT self.deposit_claim.amount = 1 self.deposit_claim.closure_time = parse_timestamp_to_utc_datetime( get_current_utc_timestamp()) self.deposit_claim.full_clean() self.deposit_claim.save() def test_that_discard_claim_should_return_false_and_not_remove_deposit_claim_if_tx_hash_is_none( self): claim_removed = discard_claim(self.deposit_claim) self.assertFalse(claim_removed) self.assertTrue( DepositClaim.objects.filter(pk=self.deposit_claim.pk).exists()) def test_that_discard_claim_should_return_true_and_remove_deposit_claim_if_tx_hash_is_set( self): self.deposit_claim.tx_hash = 64 * '0' self.deposit_claim.clean() self.deposit_claim.save() claim_removed = discard_claim(self.deposit_claim) self.assertTrue(claim_removed) self.assertFalse( DepositClaim.objects.filter(pk=self.deposit_claim.pk).exists())
class TestDepositClaimValidation(ConcentIntegrationTestCase): def setUp(self): super().setUp() task_to_compute = self._get_deserialized_task_to_compute() self.payer_ethereum_address = task_to_compute.requestor_ethereum_address self.payee_ethereum_address = task_to_compute.provider_ethereum_address client = Client(public_key_bytes=self.REQUESTOR_PUBLIC_KEY) client.clean() client.save() self.payer_deposit_account = DepositAccount() self.payer_deposit_account.client = client self.payer_deposit_account.ethereum_address = task_to_compute.requestor_ethereum_address self.payer_deposit_account.clean() self.payer_deposit_account.save() self.deposit_claim = DepositClaim() self.deposit_claim.payer_deposit_account = self.payer_deposit_account self.deposit_claim.subtask_id = task_to_compute.subtask_id self.deposit_claim.payee_ethereum_address = self.payee_ethereum_address self.deposit_claim.concent_use_case = ConcentUseCase.FORCED_TASK_RESULT.value self.deposit_claim.amount = 1 self.deposit_claim.tx_hash = encode_hex(MOCK_TRANSACTION.hash) def test_that_exception_is_raised_when_subtask_is_null_and_concent_use_case_is_not_forced_payment(self): self.deposit_claim.subtask_id = None with pytest.raises(ValidationError) as exception_info: self.deposit_claim.clean() self.assertIn('subtask_id', exception_info.value.error_dict) def test_that_exception_is_not_raised_when_subtask_is_null_and_concent_use_case_is_forced_payment(self): self.deposit_claim.subtask = None self.deposit_claim.concent_use_case = ConcentUseCase.FORCED_PAYMENT.value self.deposit_claim.clean() def test_that_exception_is_raised_when_payee_ethereum_address_is_the_same_as_payer_deposit_account_ethereum_address(self): self.deposit_claim.payee_ethereum_address = self.deposit_claim.payer_deposit_account.ethereum_address with pytest.raises(ValidationError) as exception_info: self.deposit_claim.clean() self.assertIn('payer_deposit_account', exception_info.value.error_dict) def test_that_exception_is_raised_when_payee_ethereum_address_has_wrong_length(self): self.deposit_claim.payee_ethereum_address = self.payee_ethereum_address + '1' with pytest.raises(ValidationError) as exception_info: self.deposit_claim.clean() self.assertIn('payee_ethereum_address', exception_info.value.error_dict) def test_that_exception_is_raised_when_payee_ethereum_address_has_wrong_type(self): self.deposit_claim.payee_ethereum_address = b'x' * ETHEREUM_ADDRESS_LENGTH with pytest.raises(ValidationError) as exception_info: self.deposit_claim.clean() self.assertIn('payee_ethereum_address', exception_info.value.error_dict) def test_that_exception_is_raised_when_amount_is_equal_to_zero(self): self.deposit_claim.amount = 0 with pytest.raises(ValidationError) as exception_info: self.deposit_claim.clean() self.assertIn('amount', exception_info.value.error_dict) def test_that_exception_is_raised_when_amount_is_less_then_zero(self): self.deposit_claim.amount = -1 with pytest.raises(ValidationError) as exception_info: self.deposit_claim.clean() self.assertIn('amount', exception_info.value.error_dict) def test_that_exception_is_raised_when_amount_is_of_wrong_type(self): self.deposit_claim.amount = 5.0 with pytest.raises(ValidationError): self.deposit_claim.clean() def test_that_exception_is_raised_when_tx_hash_is_not_none_and_not_string(self): self.deposit_claim.tx_hash = b'x' * ETHEREUM_TRANSACTION_HASH_LENGTH with pytest.raises(ValidationError) as exception_info: self.deposit_claim.clean() self.assertIn('tx_hash', exception_info.value.error_dict) def test_that_exception_is_raised_when_tx_hash_has_wrong_length(self): self.deposit_claim.tx_hash = encode_hex(MOCK_TRANSACTION.hash) + 'a' with pytest.raises(ValidationError) as exception_info: self.deposit_claim.clean() self.assertIn('tx_hash', exception_info.value.error_dict) def test_that_no_exception_is_raised_when_tx_hash_is_none(self): self.deposit_claim.tx_hash = None self.deposit_claim.clean() self.deposit_claim.save() def test_that_deposit_account_is_not_removed_when_deposit_claim_is_deleted(self): self.deposit_claim.clean() self.deposit_claim.save() DepositClaim.objects.filter(pk=self.deposit_claim.pk).delete() self.assertTrue( DepositAccount.objects.filter(pk=self.payer_deposit_account.pk).exists() # pylint: disable=no-member ) def test_that_no_exception_is_raised_when_deposit_claim_is_valid(self): self.deposit_claim.clean() self.deposit_claim.save()
class FinalizePaymentBanksterTest(ConcentIntegrationTestCase): def setUp(self): super().setUp() self.task_to_compute = self._get_deserialized_task_to_compute() self.subtask = store_subtask( task_id=self.task_to_compute.task_id, subtask_id=self.task_to_compute.subtask_id, provider_public_key=self.PROVIDER_PUBLIC_KEY, requestor_public_key=self.REQUESTOR_PUBLIC_KEY, state=Subtask.SubtaskState.ACCEPTED, next_deadline=None, task_to_compute=self.task_to_compute, report_computed_task=factories.tasks.ReportComputedTaskFactory( task_to_compute=self.task_to_compute)) self.subtask.full_clean() self.subtask.save() self.deposit_account = DepositAccount() self.deposit_account.client = self.subtask.requestor self.deposit_account.ethereum_address = self.task_to_compute.requestor_ethereum_address self.deposit_account.clean() self.deposit_account.save() self.deposit_claim = DepositClaim() self.deposit_claim.subtask_id = self.task_to_compute.subtask_id self.deposit_claim.payer_deposit_account = self.deposit_account self.deposit_claim.payee_ethereum_address = self.task_to_compute.provider_ethereum_address self.deposit_claim.concent_use_case = ConcentUseCase.FORCED_ACCEPTANCE self.deposit_claim.amount = 2 self.deposit_claim.clean() self.deposit_claim.save() def test_that_when_available_funds_are_zero_finalize_payment_should_delete_deposit_claim_and_return_none( self): with mock.patch('core.payments.service.get_deposit_value', return_value=0) as get_deposit_value: returned_value = finalize_payment(self.deposit_claim) self.assertIsNone(returned_value) self.assertFalse( DepositClaim.objects.filter(pk=self.deposit_claim.pk).exists()) get_deposit_value.assert_called_with( client_eth_address=self.deposit_claim.payer_deposit_account. ethereum_address, ) def test_that_when_deposit_claim_is_for_forced_acceptance_use_case_finalize_payment_should_call_force_subtask_payment( self): (v, r, s) = self.task_to_compute.promissory_note_sig with mock.patch('core.payments.service.get_deposit_value', return_value=2) as get_deposit_value: with mock.patch('core.payments.service.force_subtask_payment', return_value=MOCK_TRANSACTION_HASH ) as force_subtask_payment: returned_value = finalize_payment(self.deposit_claim) self.assertEqual(returned_value, MOCK_TRANSACTION_HASH) get_deposit_value.assert_called_with( client_eth_address=self.deposit_claim.payer_deposit_account. ethereum_address, ) force_subtask_payment.assert_called_once_with( requestor_eth_address=self.deposit_claim.payer_deposit_account. ethereum_address, provider_eth_address=self.deposit_claim.payee_ethereum_address, value=self.task_to_compute.price, subtask_id=self.deposit_claim.subtask_id, v=v, r=r, s=s, reimburse_amount=self.deposit_claim.amount) def test_that_when_deposit_claim_is_for_additional_verification_use_case_finalize_payment_should_call_cover_additional_verification_cost( self): self.deposit_claim.concent_use_case = ConcentUseCase.ADDITIONAL_VERIFICATION self.deposit_claim.clean() self.deposit_claim.save() (v, r, s) = self.task_to_compute.promissory_note_sig with mock.patch('core.payments.service.get_deposit_value', return_value=2) as get_deposit_value: with mock.patch('core.payments.service.force_subtask_payment', return_value=MOCK_TRANSACTION_HASH ) as force_subtask_payment: returned_value = finalize_payment(self.deposit_claim) self.assertEqual(returned_value, MOCK_TRANSACTION_HASH) get_deposit_value.assert_called_with( client_eth_address=self.deposit_claim.payer_deposit_account. ethereum_address, ) force_subtask_payment.assert_called_once_with( requestor_eth_address=self.deposit_claim.payer_deposit_account. ethereum_address, provider_eth_address=self.deposit_claim.payee_ethereum_address, value=self.task_to_compute.price, subtask_id=self.deposit_claim.subtask_id, v=v, r=r, s=s, reimburse_amount=self.deposit_claim.amount) def test_that_when_there_are_other_deposit_claims_finalize_payment_substract_them_from_currently_processed_claim( self): newest_deposit_claim, newest_task_to_compute = self.create_n_deposits_with_subtasks( 2) (v, r, s) = newest_task_to_compute.promissory_note_sig with mock.patch('core.payments.service.get_deposit_value', return_value=5) as get_deposit_value: with mock.patch('core.payments.service.force_subtask_payment', return_value=MOCK_TRANSACTION_HASH ) as force_subtask_payment: returned_value = finalize_payment(newest_deposit_claim) self.assertEqual(returned_value, MOCK_TRANSACTION_HASH) get_deposit_value.assert_called_with( client_eth_address=newest_deposit_claim.payer_deposit_account. ethereum_address, ) force_subtask_payment.assert_called_once_with( requestor_eth_address=newest_deposit_claim.payer_deposit_account. ethereum_address, provider_eth_address=newest_deposit_claim.payee_ethereum_address, value=newest_task_to_compute.price, subtask_id=newest_deposit_claim.subtask_id, v=v, r=r, s=s, # 5 - (2 + 2) | deposit_value - sum_of_other_claims reimburse_amount=1, ) def create_n_deposits_with_subtasks(self, n=1, amount=2): for _ in range(n): task_to_compute = self._get_deserialized_task_to_compute( provider_public_key=self._get_provider_hex_public_key(), requestor_public_key=self._get_requestor_hex_public_key(), price=amount, ) store_subtask( task_id=task_to_compute.task_id, subtask_id=task_to_compute.subtask_id, provider_public_key=self.PROVIDER_PUBLIC_KEY, requestor_public_key=self.REQUESTOR_PUBLIC_KEY, state=Subtask.SubtaskState.ACCEPTED, next_deadline=None, task_to_compute=task_to_compute, report_computed_task=factories.tasks.ReportComputedTaskFactory( task_to_compute=task_to_compute)) deposit_claim = DepositClaim() deposit_claim.subtask_id = task_to_compute.subtask_id deposit_claim.payer_deposit_account = self.deposit_account deposit_claim.payee_ethereum_address = task_to_compute.provider_ethereum_address deposit_claim.concent_use_case = ConcentUseCase.FORCED_ACCEPTANCE deposit_claim.amount = amount deposit_claim.clean() deposit_claim.save() return deposit_claim, task_to_compute
class TestDepositClaimValidation(ConcentIntegrationTestCase): def setUp(self): super().setUp() task_to_compute = self._get_deserialized_task_to_compute() self.payer_ethereum_address = task_to_compute.requestor_ethereum_address self.payee_ethereum_address = task_to_compute.provider_ethereum_address client = Client(public_key_bytes=self.REQUESTOR_PUBLIC_KEY) client.clean() client.save() self.payer_deposit_account = DepositAccount() self.payer_deposit_account.client = client self.payer_deposit_account.ethereum_address = task_to_compute.requestor_ethereum_address self.payer_deposit_account.clean() self.payer_deposit_account.save() self.deposit_claim = DepositClaim() self.deposit_claim.payer_deposit_account = self.payer_deposit_account self.deposit_claim.subtask_id = task_to_compute.subtask_id self.deposit_claim.payee_ethereum_address = self.payee_ethereum_address self.deposit_claim.concent_use_case = ConcentUseCase.FORCED_TASK_RESULT.value self.deposit_claim.amount = 1 self.deposit_claim.tx_hash = encode_hex(MOCK_TRANSACTION.hash) def test_that_exception_is_raised_when_subtask_is_null_and_concent_use_case_is_not_forced_payment( self): self.deposit_claim.subtask_id = None with pytest.raises(ValidationError) as exception_info: self.deposit_claim.clean() self.assertIn('subtask_id', exception_info.value.error_dict) def test_that_exception_is_not_raised_when_subtask_is_null_and_concent_use_case_is_forced_payment( self): self.deposit_claim.subtask = None self.deposit_claim.concent_use_case = ConcentUseCase.FORCED_PAYMENT.value self.deposit_claim.closure_time = parse_timestamp_to_utc_datetime( get_current_utc_timestamp()) self.deposit_claim.clean() def test_that_exception_is_raised_when_payee_ethereum_address_is_the_same_as_payer_deposit_account_ethereum_address( self): self.deposit_claim.payee_ethereum_address = self.deposit_claim.payer_deposit_account.ethereum_address with pytest.raises(ValidationError) as exception_info: self.deposit_claim.clean() self.assertIn('payer_deposit_account', exception_info.value.error_dict) def test_that_exception_is_raised_when_amount_is_equal_to_zero(self): self.deposit_claim.amount = 0 with pytest.raises(ValidationError) as exception_info: self.deposit_claim.clean() self.assertIn('amount', exception_info.value.error_dict) def test_that_exception_is_raised_when_amount_is_less_then_zero(self): self.deposit_claim.amount = -1 with pytest.raises(ValidationError) as exception_info: self.deposit_claim.clean() self.assertIn('amount', exception_info.value.error_dict) def test_that_exception_is_not_raised_when_amount_is_at_max_length(self): self.deposit_claim.amount = int('1' * BIG_ENDIAN_INT_MAX_DIGITS) self.deposit_claim.clean() self.deposit_claim.save() def test_that_exception_is_raised_when_tx_hash_is_not_none_and_not_string( self): self.deposit_claim.tx_hash = '11' self.deposit_claim.clean() self.deposit_claim.save() def test_that_exception_is_raised_when_closure_time_is_none_in_use_case_forced_payment( self): self.deposit_claim.concent_use_case = ConcentUseCase.FORCED_PAYMENT.value self.deposit_claim.closure_time = None with pytest.raises(ValidationError) as exception_info: self.deposit_claim.clean() self.assertIn('closure_time', exception_info.value.error_dict) def test_that_exception_is_raised_when_closure_time_is_set_in_use_case_other_than_forced_payment( self): self.deposit_claim.concent_use_case = ConcentUseCase.ADDITIONAL_VERIFICATION.value self.deposit_claim.closure_time = parse_timestamp_to_utc_datetime( get_current_utc_timestamp()) with pytest.raises(ValidationError) as exception_info: self.deposit_claim.clean() self.assertIn('closure_time', exception_info.value.error_dict) def test_that_no_exception_is_raised_when_tx_hash_is_none(self): self.deposit_claim.tx_hash = None self.deposit_claim.clean() self.deposit_claim.save() def test_that_deposit_account_is_not_removed_when_deposit_claim_is_deleted( self): self.deposit_claim.clean() self.deposit_claim.save() DepositClaim.objects.filter(pk=self.deposit_claim.pk).delete() self.assertTrue( DepositAccount.objects.filter( pk=self.payer_deposit_account.pk).exists() # pylint: disable=no-member ) def test_that_no_exception_is_raised_when_deposit_claim_is_valid(self): self.deposit_claim.clean() self.deposit_claim.save()