示例#1
0
 def add_payment(self, payment_info):
     """ Add new payment to the database.
     :param payment_info:
     """
     Payment.create(subtask=payment_info.subtask_id,
                    payee=payment_info.computer.eth_account.address,
                    value=payment_info.value)
示例#2
0
 def test_payment_big_value(self):
     value = 10000 * 10**18
     assert value > 2**64
     Payment.create(payee="me",
                    subtask="T1000",
                    value=value,
                    status=PaymentStatus.sent)
示例#3
0
 def test_invalid_value_type(self):
     with self.assertRaises(TypeError):
         Payment.create(payee="XX",
                        subtask="float",
                        value=5.5,
                        status=PaymentStatus.sent)
     with self.assertRaises(TypeError):
         Payment.create(payee="XX",
                        subtask="str",
                        value="500",
                        status=PaymentStatus.sent)
示例#4
0
 def test_payment_details(self):
     p1 = Payment(payee="me", subtask="T1000", value=123456)
     p2 = Payment(payee="you", subtask="T900", value=654321)
     self.assertNotEqual(p1.payee, p2.payee)
     self.assertNotEqual(p1.subtask, p2.subtask)
     self.assertNotEqual(p1.value, p2.value)
     self.assertEqual(p1.details, {})
     self.assertEqual(p1.details, p2.details)
     self.assertIsNot(p1.details, p2.details)
     p1.details['check'] = True
     self.assertTrue(p1.details['check'])
     self.assertNotIn('check', p2.details)
    def test_single_payment(self, *_):
        self.pp._run()
        self.gnt.create(sender=self.privkey)
        self.state.mine()
        self.check_synchronized()
        assert self.pp.gnt_balance() == 1000 * denoms.ether

        payee = urandom(20)
        b = self.pp.gnt_balance()
        # FIXME: Big values does not fit into the database
        value = random.randint(0, b / 1000)
        p1 = Payment.create(subtask="p1", payee=payee, value=value)
        assert self.pp._gnt_available() == b
        assert self.pp._gnt_reserved() == 0
        self.pp.add(p1)
        assert self.pp._gnt_available() == b - value
        assert self.pp._gnt_reserved() == value

        # Sendout.
        self.pp.deadline = int(time.time())
        self.pp._run()
        assert self.pp.gnt_balance(True) == b - value
        assert self.pp._gnt_available() == b - value
        assert self.pp._gnt_reserved() == 0

        assert self.gnt.balanceOf(payee) == value
        assert self.gnt.balanceOf(tester.a1) == self.pp._gnt_available()

        # Confirm.
        assert self.pp.gnt_balance(True) == b - value
        assert self.pp._gnt_reserved() == 0
示例#6
0
    def test_get_payments(self, *_):
        self.client = Client(datadir=self.path,
                             transaction_system=True,
                             connect_to_known_hosts=False,
                             use_docker_machine_manager=False,
                             use_monitor=False)

        payments = [
            Payment(subtask=uuid.uuid4(),
                    status=PaymentStatus.awaiting,
                    payee=str(uuid.uuid4()),
                    value=2 * 10**18,
                    created=time.time(),
                    modified=time.time()) for _ in xrange(2)
        ]

        db = Mock()
        db.get_newest_payment.return_value = payments

        self.client.transaction_system.payments_keeper.db = db
        received_payments = self.client.get_payments_list()

        self.assertEqual(len(received_payments), len(payments))

        for i in xrange(len(payments)):
            self.assertEqual(received_payments[i]['subtask'],
                             payments[i].subtask)
            self.assertEqual(received_payments[i]['status'],
                             payments[i].status.value)
            self.assertEqual(received_payments[i]['payee'],
                             unicode(payments[i].payee))
            self.assertEqual(received_payments[i]['value'],
                             unicode(payments[i].value))
示例#7
0
    def test_failed_transaction(self):
        balance_eth = 1 * denoms.ether
        balance_gntb = 99 * denoms.ether
        self.sci.get_eth_balance.return_value = balance_eth
        self.sci.get_gntb_balance.return_value = balance_gntb

        gnt_value = 10**17
        p = Payment.create(subtask="p1", payee=urandom(20), value=gnt_value)
        self.pp.add(p)

        self.pp.CLOSURE_TIME_DELAY = 0
        tx_hash = '0xdead'
        self.sci.batch_transfer.return_value = tx_hash
        assert self.pp.sendout(0)

        tx_block_number = 1337
        receipt = TransactionReceipt({
            'transactionHash': HexBytes(tx_hash),
            'blockNumber': tx_block_number,
            'blockHash': HexBytes('0x' + 64 * 'f'),
            'gasUsed': 55001,
            'status': 0,
        })
        with mock.patch('golem.ethereum.paymentprocessor.threads') as threads:
            self.sci.on_transaction_confirmed.call_args[0][1](receipt)
            threads.deferToThread.assert_called_once_with(
                self.pp._on_batch_confirmed,
                [p],
                receipt,
            )
            self.pp._on_batch_confirmed([p], receipt)
        self.assertEqual(p.status, PaymentStatus.awaiting)
        assert len(self.pp._awaiting) == 1
示例#8
0
 def test_load_from_db_sent(self):
     tx_hash1 = encode_hex(urandom(32))
     tx_hash2 = encode_hex(urandom(32))
     value = 10
     payee = urandom(20)
     sent_payment11 = Payment.create(
         subtask=str(uuid.uuid4()),
         payee=payee,
         value=value,
         details=PaymentDetails(tx=tx_hash1[2:]),
         status=PaymentStatus.sent)
     sent_payment12 = Payment.create(
         subtask=str(uuid.uuid4()),
         payee=payee,
         value=value,
         details=PaymentDetails(tx=tx_hash1[2:]),
         status=PaymentStatus.sent)
     sent_payment21 = Payment.create(
         subtask=str(uuid.uuid4()),
         payee=payee,
         value=value,
         details=PaymentDetails(tx=tx_hash2[2:]),
         status=PaymentStatus.sent)
     self.pp.load_from_db()
     self.assertEqual(3 * value, self.pp.reserved_gntb)
     self.assertEqual(0, self.pp.recipients_count)
     assert self.sci.on_transaction_confirmed.call_count == 2
     assert self.sci.on_transaction_confirmed.call_args_list[0][0][0] == \
         tx_hash1
     assert self.sci.on_transaction_confirmed.call_args_list[1][0][0] == \
         tx_hash2
     with mock.patch('golem.ethereum.paymentprocessor.threads') as threads:
         self.sci.on_transaction_confirmed.call_args_list[0][0][1](
             mock.Mock())
         threads.deferToThread.assert_called_once_with(
             self.pp._on_batch_confirmed,
             [sent_payment11, sent_payment12],
             mock.ANY,
         )
         threads.reset_mock()
         self.sci.on_transaction_confirmed.call_args_list[1][0][1](
             mock.Mock())
         threads.deferToThread.assert_called_once_with(
             self.pp._on_batch_confirmed,
             [sent_payment21],
             mock.ANY,
         )
示例#9
0
 def get_newest_payment(num=30):
     """ Return specific number of recently modified payments
     :param num: number of payments to return
     :return:
     """
     query = Payment.select().order_by(
         Payment.modified_date.desc()).limit(num)
     return query.execute()
示例#10
0
 def get_subtasks_payments(subtask_ids: Iterable[str]) -> List[Payment]:
     return list(
         Payment.select(
             Payment.subtask,
             Payment.value,
             Payment.details,
             Payment.status,
         ).where(Payment.subtask.in_(subtask_ids), ))
    def test_no_gnt_available(self):
        self.pp.start()
        self.gnt.create(sender=self.privkey)
        self.state.mine()
        self.check_synchronized()
        assert self.pp.gnt_balance() == 1000 * denoms.ether

        payee = urandom(20)
        b = self.pp.gnt_balance()
        value = b / 5 - 100
        for i in range(5):
            subtask_id = 's{}'.format(i)
            p = Payment.create(subtask=subtask_id, payee=payee, value=value)
            assert self.pp.add(p)

        q = Payment.create(subtask='F', payee=payee, value=value)
        assert not self.pp.add(q)
    def test_add_failure(self):
        a1 = urandom(20)
        a2 = urandom(20)
        p1 = Payment.create(subtask="p1", payee=a1, value=1)
        p2 = Payment.create(subtask="p2", payee=a2, value=2)

        assert p1.status is PaymentStatus.awaiting
        assert p2.status is PaymentStatus.awaiting

        self.client.get_balance.return_value = 0
        assert self.pp.add(p1) is False
        assert self.pp.add(p2) is False
        self.client.get_balance.assert_called_once_with(
            '0x' + self.addr.encode('hex'))

        assert p1.status is PaymentStatus.awaiting
        assert p2.status is PaymentStatus.awaiting
    def test_payment_deadline(self):
        a1 = urandom(20)
        a2 = urandom(20)
        a3 = urandom(20)

        self.client.get_balance.return_value = 100 * denoms.ether
        self.client.call.return_value = hex(100 * denoms.ether)[:-1]

        now = int(time.time())
        assert self.pp.add(Payment.create(subtask="p1", payee=a1, value=1))
        assert check_deadline(self.pp.deadline, now + self.pp.DEFAULT_DEADLINE)

        assert self.pp.add(Payment.create(subtask="p2", payee=a2, value=1),
                           deadline=20000)
        assert check_deadline(self.pp.deadline, now + self.pp.DEFAULT_DEADLINE)

        assert self.pp.add(Payment.create(subtask="p3", payee=a2, value=1),
                           deadline=1)
        assert check_deadline(self.pp.deadline, now + 1)

        assert self.pp.add(Payment.create(subtask="p4", payee=a3, value=1))
        assert check_deadline(self.pp.deadline, now + 1)

        assert self.pp.add(Payment.create(subtask="p5", payee=a3, value=1),
                           deadline=1)
        assert check_deadline(self.pp.deadline, now + 1)

        assert self.pp.add(Payment.create(subtask="p6", payee=a3, value=1),
                           deadline=0)
        assert check_deadline(self.pp.deadline, now)

        assert self.pp.add(Payment.create(subtask="p7", payee=a3, value=1),
                           deadline=-1)
        assert check_deadline(self.pp.deadline, now - 1)
    def test_add_invalid_payment_status(self):
        a1 = urandom(20)
        p1 = Payment.create(subtask="p1",
                            payee=a1,
                            value=1,
                            status=PaymentStatus.confirmed)
        assert p1.status is PaymentStatus.confirmed

        with self.assertRaises(RuntimeError):
            self.pp.add(p1)
示例#15
0
    def add(self, payment: Payment) -> int:
        if payment.status is not PaymentStatus.awaiting:
            raise RuntimeError("Invalid payment status: {}".format(
                payment.status))

        log.info("Payment {:.6} to {:.6} ({:.6f})".format(
            payment.subtask, encode_hex(payment.payee),
            payment.value / denoms.ether))

        if not payment.processed_ts:
            payment.processed_ts = get_timestamp()
            payment.save()

        self._awaiting.add(payment)

        self._gntb_reserved += payment.value

        log.info("GNTB reserved %.6f", self._gntb_reserved / denoms.ether)
        return payment.processed_ts
示例#16
0
 def change_state(self, subtask_id, state):
     """ Change state for all payments for task_id
     :param str subtask_id: change state of all payments that should be done for computing this task
     :param state: new state
     :return:
     """
     # FIXME: Remove this method
     query = Payment.update(status=state, modified_date=str(datetime.now()))
     query = query.where(Payment.subtask == subtask_id)
     query.execute()
示例#17
0
    def test_create(self):
        p = Payment(payee="DEF",
                    subtask="xyz",
                    value=5,
                    status=PaymentStatus.awaiting)
        self.assertEquals(p.save(force_insert=True), 1)
        with self.assertRaises(IntegrityError):
            Payment.create(payee="DEF",
                           subtask="xyz",
                           value=5,
                           status=PaymentStatus.awaiting)
        Payment.create(payee="DEF",
                       subtask="xyz2",
                       value=4,
                       status=PaymentStatus.confirmed)
        Payment.create(payee="DEF2",
                       subtask="xyz4",
                       value=5,
                       status=PaymentStatus.sent)

        self.assertEqual(3, len([payment for payment in Payment.select()]))
示例#18
0
    def test_payment_timestamp(self):
        self.sci.get_eth_balance.return_value = denoms.ether

        ts = 7000000
        p = Payment.create(subtask="p1", payee=urandom(20), value=1)
        with freeze_time(timestamp_to_datetime(ts)):
            self.pp.add(p)
        self.assertEqual(ts, p.processed_ts)

        new_ts = 900000
        with freeze_time(timestamp_to_datetime(new_ts)):
            self.pp.add(p)
        self.assertEqual(ts, p.processed_ts)
示例#19
0
 def get_state(self, payment_info):
     """ Return state of a payment for given task that should be / was made to given node
     :return str|None: return state of payment or none if such payment don't exist in database
     """
     # FIXME: Remove this method
     try:
         return Payment.get(
             Payment.subtask == payment_info.subtask_id).status
     except Payment.DoesNotExist:
         logger.warning(
             "Payment for subtask {} to node {} does not exist".format(
                 payment_info.subtask_id, payment_info.computer.key_id))
         return None
示例#20
0
    def test_monitor_progress(self):
        balance_eth = 1 * denoms.ether
        balance_gntb = 99 * denoms.ether
        gas_price = 10**9
        self.sci.get_eth_balance.return_value = balance_eth
        self.sci.get_gntb_balance.return_value = balance_gntb
        self.sci.get_transaction_gas_price.return_value = gas_price
        self.pp.CLOSURE_TIME_DELAY = 0

        assert self.pp.reserved_gntb == 0
        assert self.pp.recipients_count == 0

        gnt_value = 10**17
        p = Payment.create(subtask="p1", payee=urandom(20), value=gnt_value)
        self.pp.add(p)
        assert self.pp.reserved_gntb == gnt_value
        assert self.pp.recipients_count == 1

        tx_hash = '0xdead'
        self.sci.batch_transfer.return_value = tx_hash
        assert self.pp.sendout(0)
        assert self.sci.batch_transfer.call_count == 1
        self.sci.on_transaction_confirmed.assert_called_once_with(
            tx_hash,
            mock.ANY,
        )

        tx_block_number = 1337
        self.sci.get_block_number.return_value = tx_block_number
        receipt = TransactionReceipt({
            'transactionHash': HexBytes(tx_hash),
            'blockNumber': tx_block_number,
            'blockHash': HexBytes('0x' + 64 * 'f'),
            'gasUsed': 55001,
            'status': 1,
        })
        with mock.patch('golem.ethereum.paymentprocessor.threads') as threads:
            self.sci.on_transaction_confirmed.call_args[0][1](receipt)
            threads.deferToThread.assert_called_once_with(
                self.pp._on_batch_confirmed,
                [p],
                receipt,
            )
            self.pp._on_batch_confirmed([p], receipt)

        self.assertEqual(p.status, PaymentStatus.confirmed)
        self.assertEqual(p.details.block_number, tx_block_number)
        self.assertEqual(p.details.block_hash, 64 * 'f')
        self.assertEqual(p.details.fee, 55001 * gas_price)
        self.assertEqual(self.pp.reserved_gntb, 0)
示例#21
0
    def test_load_from_db_awaiting(self):
        self.assertEqual([], self.pp._awaiting)

        value = 10
        payment = Payment.create(
            subtask=str(uuid.uuid4()),
            payee=urandom(20),
            value=value,
        )

        self.pp.load_from_db()
        expected = [payment]
        self.assertEqual(expected, self.pp._awaiting)
        self.assertEqual(value, self.pp.reserved_gntb)
        self.assertLess(0, self.pp.recipients_count)
示例#22
0
 def add_payment_info(self, task_id, subtask_id, value, account_info):
     """ Add to payment keeper information about new payment for subtask.
     :param str task_id:    ID if a task the payment is related to.
     :param str subtask_id: the id of the compleated
                            subtask this payment is for.
     :param int value:      Aggreed value of the computed subtask.
     :param AccountInfo account_info: Billing account.
     :raise ValueError:     In case of incorrect payee address
     """
     payee = account_info.eth_account.address
     if len(payee) != 20:
         raise ValueError(
             "Incorrect 'payee' length: {}. Should be 20".format(
                 len(payee)))
     return Payment.create(subtask=subtask_id, payee=payee, value=value)
    def test_payment_deadline_not_reached(self):
        a1 = urandom(20)

        self.client.get_balance.return_value = 100 * denoms.ether
        self.client.call.return_value = hex(100 * denoms.ether)[:-1]

        now = int(time.time())
        inf = now + 12 * 30 * 24 * 60 * 60
        deadline = self.pp.deadline
        assert self.pp.deadline > inf
        assert not self.pp.sendout()
        assert self.pp.deadline == deadline

        p = Payment.create(subtask="p1", payee=a1, value=1111)
        assert self.pp.add(p, deadline=1111)
        assert check_deadline(self.pp.deadline, now + 1111)
        assert not self.pp.sendout()
        assert check_deadline(self.pp.deadline, now + 1111)
    def test_payment_aggregation(self):
        a1 = urandom(20)
        a2 = urandom(20)
        a3 = urandom(20)

        self.client.get_balance.return_value = 100 * denoms.ether
        self.client.call.return_value = hex(100 * denoms.ether)[:-1]

        assert self.pp.add(Payment.create(subtask="p1", payee=a1, value=1))
        assert self.pp.add(Payment.create(subtask="p2", payee=a2, value=1))
        assert self.pp.add(Payment.create(subtask="p3", payee=a2, value=1))
        assert self.pp.add(Payment.create(subtask="p4", payee=a3, value=1))
        assert self.pp.add(Payment.create(subtask="p5", payee=a3, value=1))
        assert self.pp.add(Payment.create(subtask="p6", payee=a3, value=1))

        self.pp.deadline = int(time.time())
        assert self.pp.sendout()
        assert self.client.send.call_count == 1
        tx = self.client.send.call_args[0][0]
        assert tx.value == 0
        assert len(
            tx.data) == 4 + 2 * 32 + 3 * 32  # Id + array abi + bytes32[3]
示例#25
0
 def add_payment(subtask_id: str, eth_address: bytes, value: int):
     """ Add new payment to the database.
     :param payment_info:
     """
     Payment.create(subtask=subtask_id, payee=eth_address, value=value)
示例#26
0
 def test_default_fields(self):
     p = Payment()
     self.assertGreaterEqual(datetime.now(), p.created_date)
     self.assertGreaterEqual(datetime.now(), p.modified_date)
示例#27
0
 def test_invalid_status(self):
     with self.assertRaises(TypeError):
         Payment.create(payee="XX", subtask="zz", value=5, status=1)
示例#28
0
 def get_payment_for_subtask(subtask_id):
     try:
         return Payment.get(Payment.subtask == subtask_id).value
     except Payment.DoesNotExist:
         logger.debug("Can't get payment value - payment does not exist")
         return 0
    def test_monitor_progress(self):
        a1 = urandom(20)

        inprogress = self.pp._inprogress

        # Give 1 ETH and 99 GNT
        balance_eth = 1 * denoms.ether
        balance_gnt = 99 * denoms.ether
        self.client.get_balance.return_value = balance_eth
        self.client.call.return_value = hex(balance_gnt)[:-1]  # Skip L suffix.

        assert self.pp._gnt_reserved() == 0
        assert self.pp._gnt_available() == balance_gnt
        assert self.pp._eth_reserved() == 0
        assert self.pp._eth_available() == balance_eth

        gnt_value = 10**17
        p = Payment.create(subtask="p1", payee=a1, value=gnt_value)
        assert self.pp.add(p)
        assert self.pp._gnt_reserved() == gnt_value
        assert self.pp._gnt_available() == balance_gnt - gnt_value
        assert self.pp._eth_reserved(
        ) == PaymentProcessor.SINGLE_PAYMENT_ETH_COST
        assert self.pp._eth_available(
        ) == balance_eth - PaymentProcessor.SINGLE_PAYMENT_ETH_COST

        self.pp.deadline = int(time.time())
        assert self.pp.sendout()
        assert self.client.send.call_count == 1
        tx = self.client.send.call_args[0][0]
        assert tx.value == 0
        assert len(tx.data) == 4 + 2 * 32 + 32  # Id + array abi + bytes32[1]

        assert len(inprogress) == 1
        assert tx.hash in inprogress
        assert inprogress[tx.hash] == [p]

        # Check payment status in the Blockchain
        self.client.get_transaction_receipt.return_value = None
        self.client.call.return_value = hex(balance_gnt -
                                            gnt_value)[:-1]  # Skip L suffix.
        self.pp.monitor_progress()
        assert len(inprogress) == 1
        assert tx.hash in inprogress
        assert inprogress[tx.hash] == [p]
        assert self.pp.gnt_balance(True) == balance_gnt - gnt_value
        assert self.pp._gnt_reserved() == 0
        assert self.pp._gnt_available() == balance_gnt - gnt_value
        assert self.pp._eth_reserved(
        ) == PaymentProcessor.SINGLE_PAYMENT_ETH_COST
        assert self.pp._eth_available(
        ) == balance_eth - PaymentProcessor.SINGLE_PAYMENT_ETH_COST

        self.pp.monitor_progress()
        assert len(inprogress) == 1
        assert self.pp._gnt_reserved() == 0
        assert self.pp._gnt_available() == balance_gnt - gnt_value
        assert self.pp._eth_reserved(
        ) == PaymentProcessor.SINGLE_PAYMENT_ETH_COST
        assert self.pp._eth_available(
        ) == balance_eth - PaymentProcessor.SINGLE_PAYMENT_ETH_COST

        receipt = {
            'blockNumber': 8214,
            'blockHash': '0x' + 64 * 'f',
            'gasUsed': 55001
        }
        self.client.get_transaction_receipt.return_value = receipt
        self.pp.monitor_progress()
        assert len(inprogress) == 0
        assert p.status == PaymentStatus.confirmed
        assert p.details['block_number'] == 8214
        assert p.details['block_hash'] == 64 * 'f'
        assert p.details['fee'] == 55001 * self.pp.GAS_PRICE
        assert self.pp._gnt_reserved() == 0