コード例 #1
0
ファイル: test_tasks.py プロジェクト: Lichtsucher/purepool
class cleanup_solutionsTestCase(TestCase):
    def setUp(self):
        self.miner = Miner()
        self.miner.save()

        self.worker = Worker(miner=self.miner)
        self.worker.save()

    def test_cleanup(self):
        older = timezone.now() - datetime.timedelta(
            days=settings.POOL_CLEANUP_MAXDAYS + 8)

        # an older entry
        work = Work(worker=self.worker, ip="1.1.1.1")
        work.save()
        work.inserted_at = older
        work.save()

        # and a new work entry
        work2 = Work(worker=self.worker, ip="2.2.2.2")
        work2.save()

        self.assertEqual(len(Work.objects.all()), 2)

        cleanup_solutions()

        self.assertEqual(len(Work.objects.all()), 1)
        self.assertEqual(Work.objects.all()[0].ip, '2.2.2.2')
コード例 #2
0
ファイル: test_tasks.py プロジェクト: Lichtsucher/purepool
    def setUp(self):
        self.miner = Miner()
        self.miner.save()

        self.worker = Worker(miner=self.miner)
        self.worker.save()

        self.work = Work(
            hash_target=
            "0000000111100000000000000000000000000000000000000000000000000000",
            worker=self.worker,
            ip="1.1.1.1")
        self.work.save()

        self.solution_string = SolutionString()
        self.solution_string.content = {
            'transaction_hex': 'TransHex',
            'thread_hash_counter': '332694',
            'prev_block_time': '1518041437',
            'prev_height': '19309',
            'nonce': '14217',
            'block_hash': 'ABCD',
            'miner_id': self.miner.id,
            'work_id': self.work.id,
            'block_time': '1518041523',
            'thread_id': '0',
            'timer_start': '1518037739857',
            'thread_start': '1518040817888',
            'bible_hash':
            '0000000e5bced1fccc7110dfd386cf461b82852ce4eec5e124ca8f5e5bcc5a11',
            'hash_counter': '1769512',
            'timer_end': '1518041527556',
            'block_hex': 'BlockHex'
        }
        self.solution_s = self.solution_string.as_string()
コード例 #3
0
ファイル: test_tasks.py プロジェクト: Lichtsucher/purepool
    def setUp(self):
        self.miner = Miner()
        self.miner.save()

        self.solution_string = SolutionString()
        self.solution_string.content = {
            'miner_id': self.miner.id,
        }
コード例 #4
0
    def setUp(self):
        self.miner = Miner(network="test",
                           address="B91RjV9UoZa5qLNbWZFXJ42sFWbJCyxxxx")
        self.miner.save()

        self.block_time = datetime.datetime(2017,
                                            9,
                                            9,
                                            11,
                                            12,
                                            13,
                                            15,
                                            tzinfo=datetime.timezone.utc)
コード例 #5
0
ファイル: test_models.py プロジェクト: Lichtsucher/purepool
class MinerCalculationTestCase(TestCase):
    def setUp(self):
        self.miner1 = Miner(network="test",
                            address="B91RjV9UoZa5qLNbWZFXJ42sFWbJCyxxxx")
        self.miner1.save()

        self.miner2 = Miner(network="test",
                            address="B91RjV9UoZa5qLNbWZFXJ42sFWbJCyxxx2")
        self.miner2.save()

        Transaction(miner=self.miner1, network="test", amount=10).save()
        Transaction(miner=self.miner1, network="test", amount=5).save()
        Transaction(miner=self.miner1, network="test", amount=-2).save()

        # should not happen, but better safe then sorry
        Transaction(miner=self.miner1, network="main", amount=100).save()

        Transaction(miner=self.miner2, network="test", amount=99).save()
        Transaction(miner=self.miner2, network="test", amount=-90).save()

    def test_basic(self):
        self.miner1.update_balance()
        self.miner2.update_balance()

        self.assertEqual(self.miner1.balance, 13)
        self.assertEqual(self.miner2.balance, 9)
コード例 #6
0
ファイル: test_tasks.py プロジェクト: Lichtsucher/purepool
    def setUp(self):
        # the miner 1 starts with a fake balance
        self.miner1 = Miner(network="test",
                            balance=20,
                            address="B91RjV9UoZa5qLNbWZFXJ42sFWbJCyxxxx")
        self.miner1.save()

        # as the user above, but with not enough balance
        self.miner2 = Miner(network="test",
                            balance=1,
                            address="B91RjV9UoZa5qLNbWZFXJ42sFWbJCyxxx2")
        self.miner2.save()

        Transaction(miner=self.miner1, amount=4, network="test").save()
        Transaction(miner=self.miner2, amount=1, network="test").save()
コード例 #7
0
    def handle(self, *args, **options):
        super(Command, self).handle(*args, **options)

        miner = Miner.objects.get(pk=options['miner_id'])
                
        value = Miner.calculate_miner_balance(miner.network, miner.id)
        
        miner.balance = value
        miner.save()
コード例 #8
0
ファイル: test_models.py プロジェクト: Lichtsucher/purepool
    def setUp(self):
        self.miner1 = Miner(network="test",
                            address="B91RjV9UoZa5qLNbWZFXJ42sFWbJCyxxxx")
        self.miner1.save()

        self.miner2 = Miner(network="test",
                            address="B91RjV9UoZa5qLNbWZFXJ42sFWbJCyxxx2")
        self.miner2.save()

        Transaction(miner=self.miner1, network="test", amount=10).save()
        Transaction(miner=self.miner1, network="test", amount=5).save()
        Transaction(miner=self.miner1, network="test", amount=-2).save()

        # should not happen, but better safe then sorry
        Transaction(miner=self.miner1, network="main", amount=100).save()

        Transaction(miner=self.miner2, network="test", amount=99).save()
        Transaction(miner=self.miner2, network="test", amount=-90).save()
コード例 #9
0
ファイル: test_tasks.py プロジェクト: Lichtsucher/purepool
    def setUp(self):
        self.miner = Miner()
        self.miner.save()

        self.worker = Worker(miner=self.miner)
        self.worker.save()

        self.solution_string = SolutionString()
        self.solution_string.content = {
            'transaction_hex':
            '01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff05026e4b0103ffffffff01ca6940057a0100001976a914e83c22b58de63a91952524084f46415c985d715c88acfdce013c5645523e312e302e382e363c2f5645523e3c4d494e4552475549443e65656635636263622d663637332d343230332d613739312d6637373362313737663164663c2f4d494e4552475549443e3c706f6c6d6573736167653e666531313263363532643964643063663436326135333762636466363561323537663461613331303032396666373432383964396366623665303161396662623c2f706f6c6d6573736167653e3c706f6c7765696768743e35363438302e35313c2f706f6c7765696768743e3c706f6c616d6f756e743e31363437342e30303c2f706f6c616d6f756e743e3c706f6c6176676167653e332e3432393c2f706f6c6176676167653e3c5349475f303e494d3736436d344e57376e554e78614e5050797662373473424d437945586e314d49347339376b4f334d475a6469672f496a59486c48594139637346616b3769756451536c6769596f643366756d4c2f44797075706e593d3c2f5349475f303e3c5349475f313e494e684d7a47487658727a4b654366424e384d4c584671466b45495a36455758694a572f6535334e73384e4c5652755274535877395830337937452b46447a7a68455762744756543868307a42477751484c33305930513d3c2f5349475f313e00000000',
            'thread_hash_counter':
            '332694',
            'prev_block_time':
            '1518041437',
            'prev_height':
            '19309',
            'nonce':
            '14217',
            'block_hash':
            '4adfaf0c3ad50afecad53ad1e57340e9735bca7d104b2b3565835a346e1c6c96',
            'miner_id':
            self.miner.id,
            'work_id':
            'b0181b3a-9868-4139-bef5-8c7e5d4239f4',
            'block_time':
            '1518041523',
            'thread_id':
            '0',
            'timer_start':
            '1518037739857',
            'thread_start':
            '1518040817888',
            'bible_hash':
            '0000000e5bced1fccc7110dfd386cf461b82852ce4eec5e124ca8f5e5bcc5a11',
            'hash_counter':
            '1769512',
            'timer_end':
            '1518041527556',
            'block_hex':
            '000000209928ce1b5ba829fde591237d3876df45daa2dd30ec31805b43dd6b972eae9aff3fab6ced6b34254aeb8c7f004cb82178984dbf22ea5c5316ac33ae6ec90ef17db3797b5aa5aa081d893700000201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff05026e4b0103ffffffff01ca6940057a0100001976a914e83c22b58de63a91952524084f46415c985d715c88acfdce013c5645523e312e302e382e363c2f5645523e3c4d494e4552475549443e65656635636263622d663637332d343230332d613739312d6637373362313737663164663c2f4d494e4552475549443e3c706f6c6d6573736167653e666531313263363532643964643063663436326135333762636466363561323537663461613331303032396666373432383964396366623665303161396662623c2f706f6c6d6573736167653e3c706f6c7765696768743e35363438302e35313c2f706f6c7765696768743e3c706f6c616d6f756e743e31363437342e30303c2f706f6c616d6f756e743e3c706f6c6176676167653e332e3432393c2f706f6c6176676167653e3c5349475f303e494d3736436d344e57376e554e78614e5050797662373473424d437945586e314d49347339376b4f334d475a6469672f496a59486c48594139637346616b3769756451536c6769596f643366756d4c2f44797075706e593d3c2f5349475f303e3c5349475f313e494e684d7a47487658727a4b654366424e384d4c584671466b45495a36455758694a572f6535334e73384e4c5652755274535877395830337937452b46447a7a68455762744756543868307a42477751484c33305930513d3c2f5349475f313e00000000010000000223e3f54cbfd562a065218f2f5be70a9d22e6ff7820dd0d1f701a53afb53767170000000049483045022100d612e1ee658823964ebdc3dedcecf2e9c19c7a9891ba264b8ba170cdfed58fbd02201d4de4c922afa8c218aa8fe6b73eadd62f00109cd777b3f7489f50eab83d3da301feffffff3fab86d7035b899793e1264899b1838fd6b988a7adc1866365dbd06250c65f260000000048473044022005004171fbc47a417c5c68e3abfd8a76e375029866b779ae117730d61ff64bab0220268e22a951608a7050747fa9e373d7610b11eb3de663f954affdf394941b777501feffffff0225b74458390000001976a9146ebc0349fad92dbb1b277ea9209609b5a485e4f988ac1f3c706f6c7765696768743e31343031312e30303c2f706f6c7765696768743ed6e9123b46010000232103dbeb934062e53b5deef24a89825b225eeea09c31037693ac7d192c5c581e1fbcac1f3c706f6c7765696768743e31343031312e30303c2f706f6c7765696768743e6d4b0000'
        }
コード例 #10
0
class WorkerIdTestCase(TestCase):
    def setUp(self):
        self.miner = Miner(address='123456', network="main")
        self.miner.save()

        self.worker = Worker(miner=self.miner, name="abc")
        self.worker.save()

    def test_parsing(self):
        with self.assertRaises(InvalidWorkerdId) as e:
            worker_id = WorkerId('')

        with self.assertRaises(InvalidWorkerdId) as e:
            worker_id = WorkerId('/')

        with self.assertRaises(InvalidWorkerdId) as e:
            worker_id = WorkerId('//')

        worker_id = WorkerId('123456')
        self.assertEqual(worker_id.get_address(), "123456")
        self.assertEqual(worker_id.get_worker(), 'Default')
        self.assertEqual(worker_id.get_email(), None)

        worker_id = WorkerId('123456/')
        self.assertEqual(worker_id.get_address(), "123456")
        self.assertEqual(worker_id.get_worker(), 'Default')
        self.assertEqual(worker_id.get_email(), None)

        worker_id = WorkerId('123456/abc')
        self.assertEqual(worker_id.get_address(), "123456")
        self.assertEqual(worker_id.get_worker(), "abc")
        self.assertEqual(worker_id.get_email(), None)

        worker_id = WorkerId('123456/abc/[email protected]')
        self.assertEqual(worker_id.get_address(), "123456")
        self.assertEqual(worker_id.get_worker(), "abc")
        self.assertEqual(worker_id.get_email(), "*****@*****.**")

        self.assertEqual(worker_id.get_worker_obj('main'), self.worker)

        with self.assertRaises(MinerNotFound) as e:
            self.assertEqual(worker_id.get_worker_obj('test'), self.worker)
コード例 #11
0
def miner(request, network, address):
    """ the miner share statistics and transaction list """

    miner = get_object_or_404(Miner, address=address, network=network)
    share_statistics = get_miner_solution_statistics(network,
                                                     miner_id=miner.id)
    transactions = Transaction.objects.filter(
        network=network, miner=miner).order_by('-id')[0:100]
    workers = Miner.get_active_worker(network, address, 1)

    error_msgs = miner_error_message_statistic(network, miner_id=miner.id)

    return render(
        request, 'purepool/miner.html', {
            'address': address,
            'network': network,
            'miner': miner,
            'workers': workers,
            'share_statistics': share_statistics,
            'transactions': transactions,
            'error_msgs': error_msgs,
        })
コード例 #12
0
    def setUp(self):
        self.miner1 = Miner(network="test",
                            address="B91RjV9UoZa5qLNbWZFXJ42sFWbJCyxxxx")
        self.miner1.save()

        self.worker1 = Worker(miner=self.miner1)
        self.worker1.save()

        self.miner2 = Miner(network="test",
                            address="B91RjV9UoZa5qLNbWZFXJ42sFWbJCyxxx2")
        self.miner2.save()

        self.worker2 = Worker(miner=self.miner2)
        self.worker2.save()

        self.insert_age = timezone.now() - datetime.timedelta(days=3)

        Transaction(miner=self.miner2, amount=60, network="test").save()

        # test network
        #----------------

        # valid
        block1 = Block(height=1,
                       network='test',
                       process_status='BP',
                       pool_block=True,
                       subsidy=100)
        block1.save()

        # not a pool block
        block2 = Block(height=2, network='test', pool_block=False, subsidy=1)
        block2.save()

        # wrong status
        block3 = Block(height=3,
                       network='test',
                       process_status='OP',
                       pool_block=True,
                       subsidy=1)
        block3.save()

        Block.objects.all().update(inserted_at=self.insert_age)

        # not old enough
        block4 = Block(height=4,
                       network='test',
                       process_status='BP',
                       pool_block=True,
                       subsidy=1)
        block4.save()

        work_test1 = Work(worker=self.worker1, ip="1.1.1.1")
        work_test1.save()

        work_test2 = Work(worker=self.worker1, ip="1.1.1.1")
        work_test2.save()

        Solution(network='test',
                 block=block1,
                 bible_hash="1",
                 miner=self.miner1,
                 work=work_test1).save()
        Solution(network='test',
                 block=block1,
                 bible_hash="2",
                 miner=self.miner1,
                 work=work_test1).save()
        Solution(network='test',
                 block=block1,
                 bible_hash="3",
                 miner=self.miner1,
                 work=work_test1).save()

        Solution(network='test',
                 block=block1,
                 bible_hash="4",
                 miner=self.miner2,
                 work=work_test1).save()
        Solution(network='test',
                 block=block1,
                 bible_hash="4.5",
                 miner=self.miner2,
                 work=work_test1).save()

        Solution(network='test',
                 block=block2,
                 bible_hash="5",
                 miner=self.miner1,
                 work=work_test1).save()
        Solution(network='test',
                 block=block3,
                 bible_hash="6",
                 miner=self.miner1,
                 work=work_test1).save()
        Solution(network='test',
                 block=block4,
                 bible_hash="7",
                 miner=self.miner1,
                 work=work_test1).save()

        # main network
        # -----------------
        block1 = Block(height=1,
                       network='main',
                       process_status='BP',
                       pool_block=True,
                       subsidy=1)
        block1.save()

        Block.objects.filter(network="main").update(
            inserted_at=self.insert_age)

        work_main = Work(worker=self.worker1, ip="1.1.1.1")
        work_main.save()

        Solution(network='main',
                 block=block2,
                 bible_hash="8",
                 miner=self.miner1,
                 work=work_main).save()
コード例 #13
0
class shareout_next_blockTestCase(TestCase):
    def setUp(self):
        self.miner1 = Miner(network="test",
                            address="B91RjV9UoZa5qLNbWZFXJ42sFWbJCyxxxx")
        self.miner1.save()

        self.worker1 = Worker(miner=self.miner1)
        self.worker1.save()

        self.miner2 = Miner(network="test",
                            address="B91RjV9UoZa5qLNbWZFXJ42sFWbJCyxxx2")
        self.miner2.save()

        self.worker2 = Worker(miner=self.miner2)
        self.worker2.save()

        self.insert_age = timezone.now() - datetime.timedelta(days=3)

        Transaction(miner=self.miner2, amount=60, network="test").save()

        # test network
        #----------------

        # valid
        block1 = Block(height=1,
                       network='test',
                       process_status='BP',
                       pool_block=True,
                       subsidy=100)
        block1.save()

        # not a pool block
        block2 = Block(height=2, network='test', pool_block=False, subsidy=1)
        block2.save()

        # wrong status
        block3 = Block(height=3,
                       network='test',
                       process_status='OP',
                       pool_block=True,
                       subsidy=1)
        block3.save()

        Block.objects.all().update(inserted_at=self.insert_age)

        # not old enough
        block4 = Block(height=4,
                       network='test',
                       process_status='BP',
                       pool_block=True,
                       subsidy=1)
        block4.save()

        work_test1 = Work(worker=self.worker1, ip="1.1.1.1")
        work_test1.save()

        work_test2 = Work(worker=self.worker1, ip="1.1.1.1")
        work_test2.save()

        Solution(network='test',
                 block=block1,
                 bible_hash="1",
                 miner=self.miner1,
                 work=work_test1).save()
        Solution(network='test',
                 block=block1,
                 bible_hash="2",
                 miner=self.miner1,
                 work=work_test1).save()
        Solution(network='test',
                 block=block1,
                 bible_hash="3",
                 miner=self.miner1,
                 work=work_test1).save()

        Solution(network='test',
                 block=block1,
                 bible_hash="4",
                 miner=self.miner2,
                 work=work_test1).save()
        Solution(network='test',
                 block=block1,
                 bible_hash="4.5",
                 miner=self.miner2,
                 work=work_test1).save()

        Solution(network='test',
                 block=block2,
                 bible_hash="5",
                 miner=self.miner1,
                 work=work_test1).save()
        Solution(network='test',
                 block=block3,
                 bible_hash="6",
                 miner=self.miner1,
                 work=work_test1).save()
        Solution(network='test',
                 block=block4,
                 bible_hash="7",
                 miner=self.miner1,
                 work=work_test1).save()

        # main network
        # -----------------
        block1 = Block(height=1,
                       network='main',
                       process_status='BP',
                       pool_block=True,
                       subsidy=1)
        block1.save()

        Block.objects.filter(network="main").update(
            inserted_at=self.insert_age)

        work_main = Work(worker=self.worker1, ip="1.1.1.1")
        work_main.save()

        Solution(network='main',
                 block=block2,
                 bible_hash="8",
                 miner=self.miner1,
                 work=work_main).save()

    @override_settings(
        POOL_ADDRESS={'POOL_BLOCK_MATURE_HOURS': {
            'test': 48,
            'main': 48
        }})
    @override_settings(POOL_ADDRESS={'test': 'abc', 'main': 'xyz'})
    @override_settings(POOL_FEE_PERCENT=5)
    @mock.patch('purepool.models.solution.tasks.BiblePayRpcClient.subsidy',
                return_value={
                    'subsidy': '100',
                    'recipient': 'abc'
                })
    def test_process(self, mock_subsidy):
        # sucessfull first block
        shareout_next_block('test')

        block1 = Block.objects.get(height=1, network="test")
        self.assertEqual(block1.process_status, 'FI')

        self.assertEqual(Transaction.objects.all().count(), 3)  # 1 old, 2 new
        self.assertEqual(
            Solution.objects.filter(block=block1, processed=True).count(), 5)

        trans1 = Transaction.objects.get(miner=self.miner1)
        trans2 = Transaction.objects.get(miner=self.miner2, amount=38)

        self.assertEqual(trans1.amount, 57)
        self.assertEqual(trans1.network, "test")
        self.assertEqual(trans1.miner, self.miner1)
        self.assertEqual(trans1.category, "MS")

        self.assertEqual(trans2.amount, 38)
        self.assertEqual(trans2.network, "test")
        self.assertEqual(trans2.miner, self.miner2)
        self.assertEqual(trans2.category, "MS")

        miner1 = Miner.objects.get(pk=self.miner1.id)
        self.assertEqual(miner1.balance, 57)

        # miner 2 already had an open transaction, so the balance is higher
        miner2 = Miner.objects.get(pk=self.miner2.id)
        self.assertEqual(miner2.balance, 98)

        # no more blocks, main untouched
        # all existing blocks not fit our requirements
        shareout_next_block('test')
        shareout_next_block('test')
        shareout_next_block('test')
        shareout_next_block('test')

        self.assertEqual(Transaction.objects.all().count(),
                         3)  # old old, 2 new

        block2 = Block.objects.get(height=2, network="test")
        self.assertEqual(block2.process_status, 'OP')

        block3 = Block.objects.get(height=3, network="test")
        self.assertEqual(block3.process_status, 'OP')

        block4 = Block.objects.get(height=4, network="test")
        self.assertEqual(block4.process_status, 'BP')

        blockmain = Block.objects.get(height=1, network="main")
        self.assertEqual(blockmain.process_status, 'BP')

    @override_settings(
        POOL_ADDRESS={'POOL_BLOCK_MATURE_HOURS': {
            'test': 48,
            'main': 48
        }})
    @override_settings(POOL_ADDRESS={'test': 'abc', 'main': 'xyz'})
    def test_stale(self):

        # not our block (anymore)?
        with mock.patch(
                'purepool.models.solution.tasks.BiblePayRpcClient.subsidy',
                return_value={"XXX": 'xxx'}):
            # marked as stale
            shareout_next_block('test')

        block1 = Block.objects.get(height=1, network="test")
        self.assertEqual(block1.process_status, 'ST')

        self.assertEqual(Transaction.objects.all().count(), 1)  # one old

    @override_settings(POOL_BLOCK_MATURE_HOURS={'test': 48, 'main': 48})
    @override_settings(POOL_ADDRESS={'test': 'abc', 'main': 'xyz'})
    def test_process_noshares(self):
        # remove all shares and test

        Solution.objects.all().delete()

        with mock.patch(
                'purepool.models.solution.tasks.BiblePayRpcClient.subsidy',
                return_value={
                    'subsidy': '55',
                    'recipient': 'abc'
                }):
            shareout_next_block('test')

        block1 = Block.objects.get(height=1, network="test")
        self.assertEqual(block1.process_status, 'FI')

        self.assertEqual(Transaction.objects.all().count(), 1)  # one old

    @override_settings(
        POOL_ADDRESS={'POOL_BLOCK_MATURE_HOURS': {
            'test': 48,
            'main': 48
        }})
    @override_settings(POOL_ADDRESS={'test': 'abc', 'main': 'xyz'})
    def test_process_nosubsidy(self):
        # set subsidy to of all blocks

        Block.objects.all().update(subsidy=0)

        with mock.patch(
                'purepool.models.solution.tasks.BiblePayRpcClient.subsidy',
                return_value={
                    'subsidy': '0',
                    'recipient': 'abc'
                }):
            # should be marked as FI
            shareout_next_block('test')

        block1 = Block.objects.get(height=1, network="test")
        self.assertEqual(block1.process_status, 'FI')

        self.assertEqual(Transaction.objects.all().count(), 1)  # one old
コード例 #14
0
    def setUp(self):
        miner = Miner(address="B91RjV9UoZa5qLNbWZFXJ42sFWbJCyxxxx")
        miner.save()

        worker = Worker(miner=miner)
        worker.save()

        work_test = Work(worker=worker, ip="1.1.1.1")
        work_test.save()

        work_main = Work(worker=worker, ip="1.1.1.1")
        work_main.save()

        # first, we add some blocks in both networks,
        # with only some being pool bocks
        self.block1_main = Block(height=4,
                                 network='main',
                                 miner=miner,
                                 subsidy=1)
        self.block1_main.save()

        self.block2_main = Block(height=4,
                                 network='main',
                                 pool_block=True,
                                 miner=miner,
                                 subsidy=1)
        self.block2_main.save()

        self.block1_test = Block(height=5,
                                 network='test',
                                 pool_block=True,
                                 miner=miner,
                                 subsidy=1)
        self.block1_test.save()

        self.block2_test = Block(height=6,
                                 network='test',
                                 miner=miner,
                                 subsidy=1)
        self.block2_test.save()

        self.block2_test = Block(height=7,
                                 network='test',
                                 pool_block=True,
                                 miner=miner,
                                 subsidy=1)
        self.block2_test.save()

        # next we set the inserted_time for two of the blocks
        # to match the solutions
        self.block1_test.inserted_at = timezone.now() - datetime.timedelta(
            days=4)
        self.block1_test.save()

        self.block2_test.inserted_at = timezone.now() - datetime.timedelta(
            days=1)
        self.block2_test.save()

        # and now some solutions to attch to the block
        s1 = Solution(network='test',
                      bible_hash="1",
                      miner=miner,
                      work=work_test)
        s1.save()
        s1.inserted_at = timezone.now() - datetime.timedelta(days=5)
        s1.save()

        s2 = Solution(network='test',
                      bible_hash="2",
                      miner=miner,
                      work=work_test)
        s2.save()
        s2.inserted_at = timezone.now() - datetime.timedelta(days=2)
        s2.save()

        s3 = Solution(network='test',
                      bible_hash="3",
                      miner=miner,
                      work=work_test)
        s3.save()

        s4 = Solution(network='main',
                      bible_hash="4",
                      miner=miner,
                      work=work_main)
        s4.save()
        s4.inserted_at = timezone.now() - datetime.timedelta(days=10)
        s4.save()
コード例 #15
0
ファイル: test_tasks.py プロジェクト: Lichtsucher/purepool
class send_autopaymentsTestCase(TestCase):
    def setUp(self):
        # the miner 1 starts with a fake balance
        self.miner1 = Miner(network="test",
                            balance=20,
                            address="B91RjV9UoZa5qLNbWZFXJ42sFWbJCyxxxx")
        self.miner1.save()

        # as the user above, but with not enough balance
        self.miner2 = Miner(network="test",
                            balance=1,
                            address="B91RjV9UoZa5qLNbWZFXJ42sFWbJCyxxx2")
        self.miner2.save()

        Transaction(miner=self.miner1, amount=4, network="test").save()
        Transaction(miner=self.miner2, amount=1, network="test").save()

    @override_settings(POOL_MINIMUM_AUTOSEND={'main': 10, 'test': 10})
    @mock.patch('puretransaction.tasks.BiblePayRpcClient.sendtoaddress',
                return_value="TXTEST")
    @mock.patch('time.sleep', return_value="")
    def test_wrongvalue(self, mock_sendtoaddress, mock_sleep):
        # balance in Miner table is higher then the real balance
        send_autopayments("test")

        miner1 = Miner.objects.get(pk=self.miner1.id)
        self.assertEqual(miner1.balance, 4)

        self.assertEqual(Transaction.objects.filter(category='TX').count(), 0)

    @override_settings(POOL_MINIMUM_AUTOSEND={'main': 10, 'test': 10})
    @mock.patch('puretransaction.tasks.BiblePayRpcClient.sendtoaddress',
                return_value="TXTEST")
    @mock.patch('time.sleep', return_value="")
    def test_outdated_value(self, mock_sendtoaddress, mock_sleep):
        # balance is high enough, but not right

        Transaction(miner=self.miner1, amount=10, network="test").save()

        send_autopayments("test")

        miner1 = Miner.objects.get(pk=self.miner1.id)
        self.assertEqual(miner1.balance, 0)

        self.assertEqual(Transaction.objects.filter(category='TX').count(), 1)

        tx = Transaction.objects.get(category='TX')
        self.assertEqual(tx.amount, -14)
        self.assertEqual(tx.miner.id, miner1.id)
        self.assertEqual(tx.network, "test")

    @override_settings(POOL_MINIMUM_AUTOSEND={'main': 10, 'test': 10})
    @mock.patch('puretransaction.tasks.BiblePayRpcClient.sendtoaddress',
                return_value="TXTEST")
    def test_error_on_send(self, mock_sendtoaddress):
        mock_sendtoaddress.side_effect = Exception()

        Transaction(miner=self.miner1, amount=10, network="test").save()

        send_autopayments("test")

    @override_settings(POOL_MINIMUM_AUTOSEND={'main': 10, 'test': 10})
    @mock.patch('puretransaction.tasks.BiblePayRpcClient.sendtoaddress',
                return_value="TXTEST")
    @mock.patch('time.sleep', return_value="")
    def test_process(self, mock_sendtoaddress, mock_sleep):
        # a successfull run

        Transaction(miner=self.miner1, amount=30, network="test").save()

        self.miner1.update_balance()
        self.miner1.save()

        Transaction(miner=self.miner1, amount=10, network="test").save()

        send_autopayments("test")

        miner1 = Miner.objects.get(pk=self.miner1.id)
        self.assertEqual(miner1.balance, 0)

        self.assertEqual(Transaction.objects.filter(category='TX').count(), 1)

        tx = Transaction.objects.get(category='TX')
        self.assertEqual(tx.amount, -44)
        self.assertEqual(tx.miner.id, miner1.id)
        self.assertEqual(tx.network, "test")

        # even with a new balance, should not pay again, as we do not pay so early again
        Transaction(miner=self.miner1, amount=16, network="test").save()

        self.miner1.update_balance()
        self.miner1.save()

        send_autopayments("test")

        miner1 = Miner.objects.get(pk=self.miner1.id)
        self.assertEqual(miner1.balance, 16)

        self.assertEqual(Transaction.objects.filter(category='TX').count(), 1)

        tx = Transaction.objects.get(category='TX')
        self.assertEqual(tx.amount, -44)
        self.assertEqual(tx.miner.id, miner1.id)
        self.assertEqual(tx.network, "test")

        # but if first_trans is older, then the second one should be paid
        tx.inserted_at = timezone.now() - datetime.timedelta(hours=18)
        tx.save()

        send_autopayments("test")

        miner1 = Miner.objects.get(pk=self.miner1.id)
        self.assertEqual(miner1.balance, 0)

        self.assertEqual(Transaction.objects.filter(category='TX').count(), 2)

        tx = Transaction.objects.filter(category='TX').order_by('-id')[0]
        self.assertEqual(tx.amount, -16)
        self.assertEqual(tx.miner.id, miner1.id)
        self.assertEqual(tx.network, "test")

    @override_settings(POOL_MINIMUM_AUTOSEND={'main': 10, 'test': 10})
    @mock.patch('puretransaction.tasks.BiblePayRpcClient.sendtoaddress',
                return_value="TXTEST")
    def test_process_failed(self, mock_sendtoaddress):
        mock_sendtoaddress.side_effect = Exception()

        # a successfull run

        Transaction(miner=self.miner1, amount=30, network="test").save()

        self.miner1.update_balance()
        self.miner1.save()

        Transaction(miner=self.miner1, amount=10, network="test").save()

        send_autopayments("test")

        miner1 = Miner.objects.get(pk=self.miner1.id)
        self.assertEqual(miner1.balance, 34)  # transaction wasn't done

        self.assertEqual(Transaction.objects.filter(category='TX').count(), 0)

        self.assertEqual(TransactionError.objects.all().count(), 1)
コード例 #16
0
class find_new_blocksTestCase(TestCase):
    def setUp(self):
        self.miner = Miner(network="test",
                           address="B91RjV9UoZa5qLNbWZFXJ42sFWbJCyxxxx")
        self.miner.save()

        self.block_time = datetime.datetime(2017,
                                            9,
                                            9,
                                            11,
                                            12,
                                            13,
                                            15,
                                            tzinfo=datetime.timezone.utc)

    @override_settings(POOL_ADDRESS={'test': 'POOLADDR'})
    def test_basic(self):
        test_block_time1 = datetime.datetime(2017,
                                             9,
                                             9,
                                             11,
                                             12,
                                             13,
                                             15,
                                             tzinfo=datetime.timezone.utc)
        test_block_time2 = datetime.datetime(2018,
                                             9,
                                             9,
                                             11,
                                             12,
                                             13,
                                             15,
                                             tzinfo=datetime.timezone.utc)
        test_block_time3 = datetime.datetime(2019,
                                             9,
                                             9,
                                             11,
                                             12,
                                             13,
                                             15,
                                             tzinfo=datetime.timezone.utc)
        test_block_time4 = datetime.datetime(2020,
                                             9,
                                             9,
                                             11,
                                             12,
                                             13,
                                             15,
                                             tzinfo=datetime.timezone.utc)

        with mock.patch('purepool.models.block.tasks.BiblePayRpcClient.subsidy') as mock_subsidy, \
             mock.patch('purepool.models.block.tasks.get_block_time') as mock_get_block_time:

            # the mock client will return the result for two block
            mock_subsidy.side_effect = [{
                'subsidy': 100,
                'minerguid': 'unknown',
                'recipient': 'POOLADDR'
            }, {
                'subsidy': 500,
                'minerguid': self.miner.id,
                'recipient': 'POOLADDR'
            }, {
                'subsidy': 200,
                'minerguid': 'xxx',
                'recipient': 'rec'
            }, None]

            mock_get_block_time.side_effect = [
                test_block_time1,
                test_block_time2,
                test_block_time3,
                test_block_time4,
            ]

            find_new_blocks('test')

            mock_subsidy.assert_has_calls(
                [mock.call(1),
                 mock.call(2),
                 mock.call(3),
                 mock.call(4)],
                any_order=False)

            block1, block2, block3 = Block.objects.all().order_by("height")

            self.assertEqual(block1.height, 1)
            self.assertTrue(block1.pool_block)
            self.assertEqual(block1.subsidy, 100)
            self.assertEqual(block1.process_status, 'OP')
            self.assertEqual(block1.miner, None)
            self.assertEqual(block1.network, 'test')
            self.assertEqual(block1.recipient, 'POOLADDR')
            self.assertEqual(block1.inserted_at, test_block_time1)

            self.assertEqual(block2.height, 2)
            self.assertTrue(block2.pool_block)
            self.assertEqual(block2.subsidy, 500)
            self.assertEqual(block2.process_status, 'OP')
            self.assertEqual(block2.miner, self.miner)
            self.assertEqual(block2.network, 'test')
            self.assertEqual(block2.recipient, 'POOLADDR')
            self.assertEqual(block2.inserted_at, test_block_time2)

            self.assertEqual(block3.height, 3)
            self.assertFalse(block3.pool_block)
            self.assertEqual(block3.subsidy, 200)
            self.assertEqual(block3.process_status, 'OP')
            self.assertEqual(block3.miner, None)
            self.assertEqual(block3.network, 'test')
            self.assertEqual(block3.recipient, 'rec')
            self.assertEqual(block3.inserted_at, test_block_time3)

            # execute a second time
            mock_subsidy.side_effect = [{
                'subsidy': 55,
                'minerguid': 'unknown',
                'recipient': 'xxx'
            }, None]

            find_new_blocks('test')

            # multiple times called with "4", as the first call
            # asks for "4" and fails on that!
            mock_subsidy.assert_has_calls([
                mock.call(1),
                mock.call(2),
                mock.call(3),
                mock.call(4),
                mock.call(4),
                mock.call(5)
            ],
                                          any_order=False)

            block1, block2, block3, block4 = Block.objects.all().order_by(
                "height")

            self.assertEqual(block4.height, 4)
            self.assertFalse(block4.pool_block)
            self.assertEqual(block4.subsidy, 55)
            self.assertEqual(block4.process_status, 'OP')
            self.assertEqual(block4.miner, None)
            self.assertEqual(block4.network, 'test')
            self.assertEqual(block4.recipient, 'xxx')
            self.assertEqual(block4.inserted_at, test_block_time4)

    def test_invalid_subsidy(self):
        with mock.patch('purepool.models.block.tasks.BiblePayRpcClient.subsidy') as mock_subsidy, \
             mock.patch('purepool.models.block.tasks.get_block_time', return_value=self.block_time):
            # the mock client will return the result for two block
            mock_subsidy.side_effect = [{'something': 'else'}]

            find_new_blocks('test')

            self.assertEqual(Block.objects.all().count(), 0)

    def test_blocknotfound(self):
        with mock.patch('purepool.models.block.tasks.BiblePayRpcClient.subsidy') as mock_subsidy, \
             mock.patch('purepool.models.block.tasks.get_block_time', return_value=self.block_time):
            mock_subsidy.side_effect = BlockNotFound()

            find_new_blocks('test')

    @override_settings(POOL_ADDRESS={'test': 'POOLADDR'})
    def test_mark_as_processed(self):
        with mock.patch('purepool.models.block.tasks.BiblePayRpcClient.subsidy') as mock_subsidy, \
             mock.patch('purepool.models.block.tasks.get_block_time', return_value=self.block_time):
            # the mock client will return the result for two block
            mock_subsidy.side_effect = [{
                'subsidy': 100,
                'minerguid': 'unknown',
                'recipient': 'POOLADDR'
            }, None]

            find_new_blocks('test', mark_as_processed=True)

            block1 = Block.objects.all().order_by("height")[0]

            self.assertEqual(block1.height, 1)
            self.assertTrue(block1.pool_block)
            self.assertEqual(block1.subsidy, 100)
            self.assertEqual(block1.process_status, 'FI')
            self.assertEqual(block1.miner, None)
            self.assertEqual(block1.network, 'test')
            self.assertEqual(block1.recipient, 'POOLADDR')

    @override_settings(POOL_ADDRESS={'test': 'POOLADDR'})
    def test_max_height(self):
        with mock.patch('purepool.models.block.tasks.BiblePayRpcClient.subsidy') as mock_subsidy, \
             mock.patch('purepool.models.block.tasks.get_block_time', return_value=self.block_time):
            # the mock client will return the result for two block
            mock_subsidy.side_effect = [{
                'subsidy': 100,
                'minerguid': 'unknown',
                'recipient': 'POOLADDR'
            }, {
                'subsidy': 100,
                'minerguid': 'unknown',
                'recipient': 'POOLADDR'
            }, {
                'subsidy': 100,
                'minerguid': 'unknown',
                'recipient': 'POOLADDR'
            }, None]

            find_new_blocks('test', max_height=1)

            self.assertEqual(Block.objects.all().count(), 1)

            block1 = Block.objects.all().order_by("height")[0]

            self.assertEqual(block1.height, 1)
            self.assertTrue(block1.pool_block)
            self.assertEqual(block1.subsidy, 100)
            self.assertEqual(block1.process_status, 'OP')
            self.assertEqual(block1.miner, None)
            self.assertEqual(block1.network, 'test')
            self.assertEqual(block1.recipient, 'POOLADDR')
コード例 #17
0
    def setUp(self):
        self.miner = Miner(address='123456', network="main")
        self.miner.save()

        self.worker = Worker(miner=self.miner, name="abc")
        self.worker.save()
コード例 #18
0
ファイル: tasks.py プロジェクト: Lichtsucher/purepool
def shareout_next_block(network, block_height=None, dry_run=False):
    """ Tries to find the oldest block that had matured and was not yet processed for
        shares. Optional, a specific block can be given.
        This task takes this block, calculates the shares of all users that contributed
        to the block and creates the transactions with there bbps.
        Important: The bbp will not send here, this is an extra step, done when the
        transaction limit is reached for a user

        Dry run will not save anything to the database.
        """

    if settings.TASK_DEBUG:
        print("Debug | ", "Shareout started with network", network,
              "on block ", block_height, " in dry-run", dry_run)

    # we only start here, if no block is currently processed
    # not important in dry_run
    if not dry_run and Block.objects.filter(
            network=network, pool_block=True, process_status='PS').count() > 0:
        if settings.TASK_DEBUG:
            print("Debug | ",
                  "Another block is currently processed/has status 'PS'")
        return

    # try to find the oldest block then is OLDER then 1 day
    # (so it had matured -> the network had accepted it) and take it
    age = timezone.now() - datetime.timedelta(
        hours=settings.POOL_BLOCK_MATURE_HOURS[network])

    if block_height is None:
        lowest_pool_waiting_height = Block.objects.filter(
            network=network,
            pool_block=True,
            process_status='BP',
            inserted_at__lt=age).aggregate(Min('height'))['height__min']

        if lowest_pool_waiting_height is None:  # no unprocessed block found
            return
    else:
        lowest_pool_waiting_height = block_height

    block = Block.objects.get(network=network,
                              height=lowest_pool_waiting_height)

    if settings.TASK_DEBUG:
        print("Debug | ", "Loaded block from database:", block.height,
              block.network, block.process_status, block.inserted_at)

    # before we start, we mark the block as in-process of the shares
    with transaction.atomic():
        block.process_status = 'PS'  # Processing shares
        if not dry_run:
            block.save()

    # if we found a block, we ensure that is still ours!
    client = BiblePayRpcClient(network=network)
    subsidy = client.subsidy(lowest_pool_waiting_height)

    if settings.TASK_DEBUG:
        print("Debug | ", "Requested subsidy: ", subsidy)

    if subsidy.get('recipient') != settings.POOL_ADDRESS[network]:
        block.process_status = 'ST'  # stale
        if not dry_run:
            block.save()
        return

    # now we count the users solutions for the block
    # Important: Do not remove the ".order_by()", as it is required, or the result
    # will be wrong (seems to be a django problem)
    qs = Solution.objects.filter(network=network, block=block, ignore=False)

    if not dry_run:  # in reall live, we only want entries that where not already processed
        qs = qs.filter(processed=False)

    solution_counts = qs.values('miner_id').annotate(
        total=Count('miner_id')).order_by()

    # with that, we first calculate the total amount of relevant shares
    total_count = 0
    for solution_count in solution_counts:
        total_count += solution_count['total']

    if settings.TASK_DEBUG:
        print("Debug | ", "Solution count is ", total_count)
        print("Debug | ", "Miner/solution count is ", len(solution_counts))

    # if there are no shares, then there is nothing todo here anymore
    if total_count == 0:
        block.process_status = 'FI'  # finished
        if not dry_run:
            block.save()
        return

    # same if the block.subsidy is buggy
    if block.subsidy == 0:
        block.process_status = 'FI'  # finished
        if not dry_run:
            block.save()
        return

    # before we do the share calculation, we substract the fee from the subsidy
    miner_subsidy = block.subsidy
    if settings.POOL_FEE_PERCENT > 0:
        miner_subsidy = calculate_miner_subsidy(block.subsidy)

    if settings.TASK_DEBUG:
        print("Debug | ", "Miner subsidy is ", miner_subsidy)

    # calculcation of the amount of bbp per user based on the solutions of the block
    subsidy_per_solution = miner_subsidy / total_count

    if settings.TASK_DEBUG:
        print("Debug | ", "Subsidy per solution is ", subsidy_per_solution,
              "with a total of", (subsidy_per_solution * total_count))

    added_amount = 0

    # and now we add the transactions that add the coins to the user
    # they are not send to the user here, that will be done by a different script
    with transaction.atomic():
        for solution_count in solution_counts:
            user_subsidy = subsidy_per_solution * solution_count['total']

            inote = 'BLOCK:' + str(block.height) + '|SOLUTIONS:' + str(
                solution_count['total'])

            tx = Transaction(
                network=network,
                miner_id=solution_count['miner_id'],
                amount=user_subsidy,
                category='MS',

                # some notes for the user and some for us
                note='Share for block %s' % block.height,
                internal_note=inote,
            )
            if not dry_run:
                tx.save()

            added_amount += user_subsidy

        # last but not least, we mark the block and the solutions as processed
        if not dry_run:
            Solution.objects.filter(network=network,
                                    processed=False,
                                    block=block).update(processed=True)

        # and we mark the block as finished
        block.process_status = 'FI'  # finished
        if not dry_run:
            block.save()

    if settings.TASK_DEBUG:
        print("Debug | ", "Created transaction with a total amount of ",
              added_amount)

    # last, we update the user balances. We do this in a new step, as the step before is more important
    # and should be done as fast as possible
    # We do not load the miner from the database, we only update it. This is faster
    if not dry_run:
        update_list = []
        with transaction.atomic():
            for solution_count in solution_counts:
                value = Miner.calculate_miner_balance(
                    network, solution_count['miner_id'])
                Miner.objects.filter(pk=solution_count['miner_id']).update(
                    balance=value)
コード例 #19
0
ファイル: test_hash.py プロジェクト: Lichtsucher/purepool
 def setUp(self):
     self.miner = Miner(rating=0)
     self.miner.save()
コード例 #20
0
ファイル: test_tasks.py プロジェクト: Lichtsucher/purepool
class validate_solutionTestCase(TestCase):
    def setUp(self):
        self.miner = Miner()
        self.miner.save()

        self.worker = Worker(miner=self.miner)
        self.worker.save()

        self.solution_string = SolutionString()
        self.solution_string.content = {
            'transaction_hex':
            '01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff05026e4b0103ffffffff01ca6940057a0100001976a914e83c22b58de63a91952524084f46415c985d715c88acfdce013c5645523e312e302e382e363c2f5645523e3c4d494e4552475549443e65656635636263622d663637332d343230332d613739312d6637373362313737663164663c2f4d494e4552475549443e3c706f6c6d6573736167653e666531313263363532643964643063663436326135333762636466363561323537663461613331303032396666373432383964396366623665303161396662623c2f706f6c6d6573736167653e3c706f6c7765696768743e35363438302e35313c2f706f6c7765696768743e3c706f6c616d6f756e743e31363437342e30303c2f706f6c616d6f756e743e3c706f6c6176676167653e332e3432393c2f706f6c6176676167653e3c5349475f303e494d3736436d344e57376e554e78614e5050797662373473424d437945586e314d49347339376b4f334d475a6469672f496a59486c48594139637346616b3769756451536c6769596f643366756d4c2f44797075706e593d3c2f5349475f303e3c5349475f313e494e684d7a47487658727a4b654366424e384d4c584671466b45495a36455758694a572f6535334e73384e4c5652755274535877395830337937452b46447a7a68455762744756543868307a42477751484c33305930513d3c2f5349475f313e00000000',
            'thread_hash_counter':
            '332694',
            'prev_block_time':
            '1518041437',
            'prev_height':
            '19309',
            'nonce':
            '14217',
            'block_hash':
            '4adfaf0c3ad50afecad53ad1e57340e9735bca7d104b2b3565835a346e1c6c96',
            'miner_id':
            self.miner.id,
            'work_id':
            'b0181b3a-9868-4139-bef5-8c7e5d4239f4',
            'block_time':
            '1518041523',
            'thread_id':
            '0',
            'timer_start':
            '1518037739857',
            'thread_start':
            '1518040817888',
            'bible_hash':
            '0000000e5bced1fccc7110dfd386cf461b82852ce4eec5e124ca8f5e5bcc5a11',
            'hash_counter':
            '1769512',
            'timer_end':
            '1518041527556',
            'block_hex':
            '000000209928ce1b5ba829fde591237d3876df45daa2dd30ec31805b43dd6b972eae9aff3fab6ced6b34254aeb8c7f004cb82178984dbf22ea5c5316ac33ae6ec90ef17db3797b5aa5aa081d893700000201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff05026e4b0103ffffffff01ca6940057a0100001976a914e83c22b58de63a91952524084f46415c985d715c88acfdce013c5645523e312e302e382e363c2f5645523e3c4d494e4552475549443e65656635636263622d663637332d343230332d613739312d6637373362313737663164663c2f4d494e4552475549443e3c706f6c6d6573736167653e666531313263363532643964643063663436326135333762636466363561323537663461613331303032396666373432383964396366623665303161396662623c2f706f6c6d6573736167653e3c706f6c7765696768743e35363438302e35313c2f706f6c7765696768743e3c706f6c616d6f756e743e31363437342e30303c2f706f6c616d6f756e743e3c706f6c6176676167653e332e3432393c2f706f6c6176676167653e3c5349475f303e494d3736436d344e57376e554e78614e5050797662373473424d437945586e314d49347339376b4f334d475a6469672f496a59486c48594139637346616b3769756451536c6769596f643366756d4c2f44797075706e593d3c2f5349475f303e3c5349475f313e494e684d7a47487658727a4b654366424e384d4c584671466b45495a36455758694a572f6535334e73384e4c5652755274535877395830337937452b46447a7a68455762744756543868307a42477751484c33305930513d3c2f5349475f313e00000000010000000223e3f54cbfd562a065218f2f5be70a9d22e6ff7820dd0d1f701a53afb53767170000000049483045022100d612e1ee658823964ebdc3dedcecf2e9c19c7a9891ba264b8ba170cdfed58fbd02201d4de4c922afa8c218aa8fe6b73eadd62f00109cd777b3f7489f50eab83d3da301feffffff3fab86d7035b899793e1264899b1838fd6b988a7adc1866365dbd06250c65f260000000048473044022005004171fbc47a417c5c68e3abfd8a76e375029866b779ae117730d61ff64bab0220268e22a951608a7050747fa9e373d7610b11eb3de663f954affdf394941b777501feffffff0225b74458390000001976a9146ebc0349fad92dbb1b277ea9209609b5a485e4f988ac1f3c706f6c7765696768743e31343031312e30303c2f706f6c7765696768743ed6e9123b46010000232103dbeb934062e53b5deef24a89825b225eeea09c31037693ac7d192c5c581e1fbcac1f3c706f6c7765696768743e31343031312e30303c2f706f6c7765696768743e6d4b0000'
        }

    def test_basic(self):

        # work missing
        with self.assertRaises(UnknownWork):
            validate_solution('test', self.solution_string)

        # check_hashtarget fails
        work = Work(
            pk='b0181b3a-9868-4139-bef5-8c7e5d4239f4',
            hash_target=
            "0000000111100000000000000000000000000000000000000000000000000000",
            worker=self.worker,
            ip="1.1.1.1",
            network="test")
        work.save()

        with self.assertRaises(HashTargetExceeded):
            validate_solution('test', self.solution_string)

        # client.bible_hash returns different bible hash
        work.hash_target = '0000001111000000000000000000000000000000000000000000000000000000'
        work.save()

        with mock.patch(
                'purepool.models.solution.tasks.BiblePayRpcClient.bible_hash',
                return_value="1234"):
            with self.assertRaises(BibleHashWrong):
                validate_solution('test', self.solution_string)

        # from here on, we fake a valid answer for the bible_hash calculation, so that
        # succeed
        with mock.patch(
                'purepool.models.solution.tasks.BiblePayRpcClient.bible_hash',
                return_value=
                "0000000e5bced1fccc7110dfd386cf461b82852ce4eec5e124ca8f5e5bcc5a11"
        ):

            # fail if the target address in the transaction is not from the pool
            trans_result = {'recipient': 'yiCwAb9qeaQqzDX5jQZJgBQ9mRy2aqk2Tb'}
            with mock.patch(
                    'purepool.models.solution.tasks.BiblePayRpcClient.hexblocktocoinbase',
                    return_value=trans_result):
                with self.settings(POOL_ADDRESS={
                        'test': 'ABCDEFG',
                        'cpid_sig_valid': True
                }):
                    with self.assertRaises(TransactionTampered):
                        validate_solution('test', self.solution_string)

            # fail if this is an invalid TX
            with mock.patch(
                    'purepool.models.solution.tasks.BiblePayRpcClient.hexblocktocoinbase',
                    return_value=trans_result) as mock_hexblocktocoinbase:
                mock_hexblocktocoinbase.side_effect = TypeError()
                with self.assertRaises(TransactionInvalid):
                    validate_solution('test', self.solution_string)

            # the TX is valid here, but the nonce is not right!
            with self.settings(POOL_ADDRESS={'test': 'ABCDEFG'}):
                trans_result = {
                    'recipient': 'ABCDEFG',
                    'cpid_sig_valid': True,
                    'cpid_legal': True
                }
                with mock.patch(
                        'purepool.models.solution.tasks.BiblePayRpcClient.hexblocktocoinbase',
                        return_value=trans_result):
                    with mock.patch(
                            'purepool.models.solution.tasks.BiblePayRpcClient.pinfo',
                            return_value={
                                'pinfo': 3,
                                'height': 0
                            }):
                        with self.assertRaises(TransactionTampered):
                            validate_solution('test', self.solution_string)

            # Here the prev_height was faked
            with self.settings(POOL_ADDRESS={'test': 'ABCDEFG'}):
                trans_result = {
                    'recipient': 'ABCDEFG',
                    'cpid_sig_valid': True,
                    'cpid_legal': True
                }
                with mock.patch(
                        'purepool.models.solution.tasks.BiblePayRpcClient.hexblocktocoinbase',
                        return_value=trans_result):
                    with mock.patch(
                            'purepool.models.solution.tasks.BiblePayRpcClient.pinfo',
                            return_value={
                                'pinfo': 999999,
                                'height': 19
                            }):
                        with self.assertRaises(TransactionTampered):
                            validate_solution('test', self.solution_string)

            # now cpid_sig_valid is missing -> old biblepay server client
            with self.settings(POOL_ADDRESS={'test': 'ABCDEFG'}):
                trans_result = {'recipient': 'ABCDEFG'}
                with mock.patch(
                        'purepool.models.solution.tasks.BiblePayRpcClient.hexblocktocoinbase',
                        return_value=trans_result):
                    with mock.patch(
                            'purepool.models.solution.tasks.BiblePayRpcClient.pinfo',
                            return_value={
                                'pinfo': 999999,
                                'height': 19
                            }):
                        with self.assertRaises(Biblepayd_Outdated):
                            validate_solution('test', self.solution_string)

            # and now cpid_sig_valid is False
            with self.settings(POOL_ADDRESS={'test': 'ABCDEFG'}):
                trans_result = {
                    'recipient': 'ABCDEFG',
                    'cpid_sig_valid': True,
                    'cpid_legal': False
                }
                with mock.patch(
                        'purepool.models.solution.tasks.BiblePayRpcClient.hexblocktocoinbase',
                        return_value=trans_result):
                    with mock.patch(
                            'purepool.models.solution.tasks.BiblePayRpcClient.pinfo',
                            return_value={
                                'pinfo': 999999,
                                'height': 19
                            }):
                        with self.assertRaises(Illegal_CPID):
                            validate_solution('test', self.solution_string)

            # cpid_legal indicates if the user was in the last payout for Rosetta, plus it checks if the user had just solved a block
            # and can't solve a new one for the next 3 blocks
            with self.settings(POOL_ADDRESS={'test': 'ABCDEFG'}):
                trans_result = {
                    'recipient': 'ABCDEFG',
                    'cpid_sig_valid': False,
                    'cpid_legal': True
                }
                with mock.patch(
                        'purepool.models.solution.tasks.BiblePayRpcClient.hexblocktocoinbase',
                        return_value=trans_result):
                    with mock.patch(
                            'purepool.models.solution.tasks.BiblePayRpcClient.pinfo',
                            return_value={
                                'pinfo': 999999,
                                'height': 19
                            }):
                        with self.assertRaises(Invalid_CPID):
                            validate_solution('test', self.solution_string)

            # and now, with everything right, it should succeed
            with self.settings(POOL_ADDRESS={'test': 'ABCDEFG'}):
                trans_result = {
                    'recipient': 'ABCDEFG',
                    'cpid_sig_valid': True,
                    'cpid_legal': True
                }
                with mock.patch(
                        'purepool.models.solution.tasks.BiblePayRpcClient.hexblocktocoinbase',
                        return_value=trans_result):
                    with mock.patch(
                            'purepool.models.solution.tasks.BiblePayRpcClient.pinfo',
                            return_value={
                                'pinfo': 999999,
                                'height': 19309
                            }):
                        self.assertTrue(
                            validate_solution('test', self.solution_string))
コード例 #21
0
ファイル: test_tasks.py プロジェクト: Lichtsucher/purepool
    def setUp(self):
        self.miner = Miner()
        self.miner.save()

        self.worker = Worker(miner=self.miner)
        self.worker.save()
コード例 #22
0
ファイル: test_tasks.py プロジェクト: Lichtsucher/purepool
class calculate_multiplyTestCase(TestCase):
    def setUp(self):
        self.miner = Miner()
        self.miner.save()

        self.solution_string = SolutionString()
        self.solution_string.content = {
            'miner_id': self.miner.id,
        }

    def test_regular(self):
        self.miner.percent_ratio = 100
        self.miner.save()

        self.assertEqual(calculate_multiply(self.solution_string), 1)

    def test_bad(self):
        self.miner.percent_ratio = 400
        self.miner.save()

        with mock.patch('random.randrange', return_value=200):
            # multiply is inactive right now, it always returns 1
            #self.assertEqual(calculate_multiply(self.solution_string), 0)
            self.assertEqual(calculate_multiply(self.solution_string), 1)

        with mock.patch('random.randrange', return_value=50):
            self.assertEqual(calculate_multiply(self.solution_string), 1)

    def test_good(self):
        self.miner.percent_ratio = 9
        self.miner.save()

        # multiply is inactive right now, it always returns 1
        #self.assertEqual(calculate_multiply(self.solution_string), 4)
        self.assertEqual(calculate_multiply(self.solution_string), 1)

        self.miner.percent_ratio = 30
        self.miner.save()
        # multiply is inactive right now, it always returns 1
        #self.assertEqual(calculate_multiply(self.solution_string), 3)
        self.assertEqual(calculate_multiply(self.solution_string), 1)

        self.miner.percent_ratio = 50
        self.miner.save()
        # multiply is inactive right now, it always returns 1
        #self.assertEqual(calculate_multiply(self.solution_string), 2)
        self.assertEqual(calculate_multiply(self.solution_string), 1)
コード例 #23
0
ファイル: test_tasks.py プロジェクト: Lichtsucher/purepool
class process_solutionTestCase(TestCase):
    def setUp(self):
        self.miner = Miner()
        self.miner.save()

        self.worker = Worker(miner=self.miner)
        self.worker.save()

        self.work = Work(
            hash_target=
            "0000000111100000000000000000000000000000000000000000000000000000",
            worker=self.worker,
            ip="1.1.1.1")
        self.work.save()

        self.solution_string = SolutionString()
        self.solution_string.content = {
            'transaction_hex': 'TransHex',
            'thread_hash_counter': '332694',
            'prev_block_time': '1518041437',
            'prev_height': '19309',
            'nonce': '14217',
            'block_hash': 'ABCD',
            'miner_id': self.miner.id,
            'work_id': self.work.id,
            'block_time': '1518041523',
            'thread_id': '0',
            'timer_start': '1518037739857',
            'thread_start': '1518040817888',
            'bible_hash':
            '0000000e5bced1fccc7110dfd386cf461b82852ce4eec5e124ca8f5e5bcc5a11',
            'hash_counter': '1769512',
            'timer_end': '1518041527556',
            'block_hex': 'BlockHex'
        }
        self.solution_s = self.solution_string.as_string()

    def test_valid(self):

        self.assertEqual(len(Solution.objects.all()), 0)
        self.assertEqual(len(RejectedSolution.objects.all()), 0)

        with mock.patch('purepool.models.solution.tasks.validate_solution',
                        return_value=True):
            process_solution('test', self.solution_s)

        self.assertEqual(len(RejectedSolution.objects.all()), 0)
        self.assertEqual(len(Solution.objects.all()), 1)

        solution = Solution.objects.all()[0]
        self.assertEqual(solution.network, 'test')
        self.assertEqual(solution.miner_id, self.miner.id)
        self.assertEqual(solution.work_id, self.work.id)
        self.assertEqual(solution.bible_hash,
                         self.solution_string.get_bible_hash())
        self.assertEqual(solution.solution, '')  #self.solution_s)
        self.assertEqual(solution.hps, 467)

    def test_valid_multiply(self):

        self.assertEqual(len(Solution.objects.all()), 0)
        self.assertEqual(len(RejectedSolution.objects.all()), 0)

        with mock.patch('purepool.models.solution.tasks.validate_solution',
                        return_value=True):
            with mock.patch(
                    'purepool.models.solution.tasks.calculate_multiply',
                    return_value=3):
                process_solution('test', self.solution_s)

        self.assertEqual(len(RejectedSolution.objects.all()), 0)
        self.assertEqual(len(Solution.objects.all()), 3)

        solution = Solution.objects.all()[0]
        self.assertEqual(solution.network, 'test')
        self.assertEqual(solution.miner_id, self.miner.id)
        self.assertEqual(solution.work_id, self.work.id)
        self.assertEqual(solution.bible_hash,
                         self.solution_string.get_bible_hash())
        self.assertEqual(solution.solution, '')  # self.solution_s)
        self.assertEqual(solution.hps, 467)

    def test_invalid(self):

        self.assertEqual(len(Solution.objects.all()), 0)
        self.assertEqual(len(RejectedSolution.objects.all()), 0)

        with mock.patch('purepool.models.solution.tasks.validate_solution',
                        return_value=False) as mock_validate_solution:
            mock_validate_solution.side_effect = BibleHashWrong
            with self.assertRaises(BibleHashWrong):
                process_solution('test', self.solution_s)

        self.assertEqual(len(RejectedSolution.objects.all()), 1)
        self.assertEqual(len(Solution.objects.all()), 0)

        rsolution = RejectedSolution.objects.all()[0]
        self.assertEqual(rsolution.network, 'test')
        self.assertEqual(rsolution.miner_id, self.miner.id)
        self.assertEqual(rsolution.work_id, self.work.id)
        self.assertEqual(rsolution.bible_hash,
                         self.solution_string.get_bible_hash())
        self.assertEqual(rsolution.solution, self.solution_s)
        self.assertEqual(rsolution.hps, 0)
コード例 #24
0
ファイル: tasks.py プロジェクト: Lichtsucher/purepool
def send_autopayments(network):
    """ Looks into the miner list and finds all miners that
        have a balance greater than settings.POOL_MINIMUM_AUTOSEND """

    # no autosend is done if the miner has a balance below
    # this value
    minimum = settings.POOL_MINIMUM_AUTOSEND[network]

    # miners of the network with more then the minimum balance
    miners = Miner.objects.filter(balance__gt=minimum,
                                  network=network).values('id', 'address')

    client = BiblePayRpcClient(network=network)

    # the system will only do the transactions for
    # this amount of miners before this task is closed
    # the next task will go on from then on
    max_miners = 10

    miner_pos = 0
    for miner in miners:
        # we only send payments for miners who hadn't a payment in the last 12 hours
        last_trans_dt = timezone.now() - datetime.timedelta(hours=12)
        last_trans_count = Transaction.objects.filter(
            miner_id=miner['id'],
            network=network,
            category='TX',
            inserted_at__gt=last_trans_dt).count()

        if last_trans_count > 0:
            continue

        miner_pos += 1

        with transaction.atomic():
            # for security reasons, we recalculate the balance,
            # as the miner table can be changed by the frontend
            value = Miner.calculate_miner_balance(network, miner['id'])

            # if all is fine, we send out the bbp
            if value > minimum:
                tx_id = None
                try:
                    tx_id = client.sendtoaddress(miner['address'], value)
                except Exception as e:
                    error_message = ' # '.join([str(e), str(type(e))]) + "\n"
                    error_message += str(traceback.extract_stack()) + "\n"
                    error_message += str(traceback.format_stack())

                    # we should log the error if something goes wrong
                    transerror = TransactionError(
                        network=network,
                        miner_id=miner['id'],
                        amount=(value * -1),
                        error_message=error_message,
                    )
                    transerror.save()

                # transaction failed? Then we skip this user this time
                if tx_id is None:
                    continue

                internal_note = 'TX_ID:%s' % tx_id

                tx = Transaction(
                    network=network,
                    miner_id=miner['id'],
                    category='TX',  # outgoing transaction

                    # We substract the amount here, so it must be negative (55 -> -55)
                    amount=(value * -1),

                    # biblepay transaction
                    tx=tx_id,

                    # some notes for the user and some for us
                    note='Autosend',
                    internal_note=internal_note,
                )
                tx.save()

                # no value should be on the account anymore
                # but we better calculate it, if something had changed
                value = Miner.calculate_miner_balance(network, miner['id'])

                # added to prevent a problem with to fast and many transactions
                # in a short time
                time.sleep(5)

            # we update the miner with the new balance
            # even if no bbp was send (because of wrong values in the db). We
            # at least fix the value then
            Miner.objects.filter(pk=miner['id'],
                                 network=network).update(balance=value)

        # we end after we reached our max for this task
        if miner_pos == max_miners:
            break
コード例 #25
0
ファイル: test_hash.py プロジェクト: Lichtsucher/purepool
class GetHashTargetTestCase(TestCase):

    def setUp(self):
        self.miner = Miner(rating=0)
        self.miner.save()

    def test_basic(self):
        self.assertEqual(GetHashTarget(self.miner.id, 'main'), '0000011110000000000000000000000000000000000000000000000000000000')

        # NOTE: In previos versions, the rating changed the hash
        # But now, we drop them in the validate_solution task. This test ensures that the new behavior is working
        self.miner.rating = -1
        self.miner.save()
        self.assertEqual(GetHashTarget(self.miner.id, 'main'), '0000011110000000000000000000000000000000000000000000000000000000')

        self.miner.rating = -2
        self.miner.save()
        self.assertEqual(GetHashTarget(self.miner.id, 'main'), '0000011110000000000000000000000000000000000000000000000000000000')

        self.miner.rating = 1
        self.miner.save()
        self.assertEqual(GetHashTarget(self.miner.id, 'main'), '0000011110000000000000000000000000000000000000000000000000000000')
        
        self.miner.rating = 2
        self.miner.save()
        self.assertEqual(GetHashTarget(self.miner.id, 'main'), '0000011110000000000000000000000000000000000000000000000000000000')
        
        self.miner.rating = 3
        self.miner.save()
        self.assertEqual(GetHashTarget(self.miner.id, 'main'), '0000011110000000000000000000000000000000000000000000000000000000')