def test_many_miners_connect_ready_disconnect(self, qty=5):
        transport = Mock()
        connections = []
        for idx in range(qty):
            conn = StratumProtocol(self.manager)
            conn.connection_made(transport=transport)
            self.assertEqual(idx + 1, len(self.manager.connections))
            self.assertEqual(0, len(self.manager.miners))
            connections.append(conn)

        self.assertEqual(qty, len(self.manager.connections))
        self.assertEqual(0, len(self.manager.miners))

        for idx, conn in enumerate(connections):
            conn.method_subscribe(params=None, msgid=None)
            conn.method_authorize(params=None, msgid=None)
            self.assertEqual(idx + 1, len(self.manager.miners))

        self.assertEqual(qty, len(self.manager.connections))
        self.assertEqual(qty, len(self.manager.miners))
        self.manager.status()

        for idx, conn in enumerate(connections):
            conn.connection_lost(exc=None)
            self.assertEqual(qty - idx - 1, len(self.manager.connections))
            self.assertEqual(qty - idx - 1, len(self.manager.miners))

        self.assertEqual(0, len(self.manager.connections))
        self.assertEqual(0, len(self.manager.miners))
    def setUp(self):
        self.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self.loop)

        manager = MagicMock()
        transport = MagicMock()
        self.protocol = StratumProtocol(manager)
        self.protocol.connection_made(transport)
        self.protocol.current_job = MinerBlockJob(BLOCK_DATA_1, 0)
    def test_miner_some_jsonrpc_methods(self):
        conn = StratumProtocol(self.manager)
        conn.connection_made(transport=None)

        conn.send_result = MagicMock(return_value=None)
        conn.method_extranonce_subscribe(params=None, msgid=None)
        conn.send_result.assert_called_with(None, True)

        conn.send_result = MagicMock(return_value=None)
        conn.method_multi_version(params=None, msgid=None)
        conn.send_result.assert_called_with(None, True)
    def test_miner_connect_ready_disconnect(self):
        conn = StratumProtocol(self.manager)
        transport = Mock()
        conn.connection_made(transport=transport)
        self.assertEqual(1, len(self.manager.connections))
        self.assertEqual(0, len(self.manager.miners))

        conn.method_subscribe(params=None, msgid=None)
        conn.method_authorize(params=None, msgid=None)
        self.assertEqual(1, len(self.manager.miners))

        conn.connection_lost(exc=None)
        self.assertEqual(0, len(self.manager.connections))
        self.assertEqual(0, len(self.manager.miners))
 def update_miner_job(self,
                      protocol: StratumProtocol,
                      *,
                      clean: bool = False) -> None:
     """Send a new job for a miner."""
     job = self.get_best_job(protocol)
     if job is None:
         # We do not have a job for the miner. We could close the connection,
         # but we do not do it because a TxJob might arrive anytime.
         return
     # TODO Set clean based on old job vs. new job
     if isinstance(job, MinerTxJob):
         clean = True
     protocol.update_job(job, clean=clean)
    def _get_ready_miner(self, address: Optional[str] = None) -> StratumProtocol:
        conn = StratumProtocol(self.manager)
        conn._update_job_timestamp = False

        transport = Mock()
        conn.connection_made(transport=transport)

        if address:
            params = {'address': address}
        else:
            params = {}
        conn.method_subscribe(params=params, msgid=None)
        conn.method_authorize(params=None, msgid=None)
        return conn
    def test_miner_invalid_address(self):
        conn = StratumProtocol(self.manager)
        conn.send_error = MagicMock(return_value=None)

        transport = Mock()
        conn.connection_made(transport=transport)

        params = {'address': 'X'}
        conn.method_subscribe(params=params, msgid=None)
        conn.send_error.assert_called_once_with(None, conn.INVALID_ADDRESS)
 def test_miner_connect_disconnect(self):
     conn = StratumProtocol(self.manager)
     conn.connection_made(transport=None)
     self.assertEqual(1, len(self.manager.connections))
     self.assertEqual(0, len(self.manager.miners))
     conn.connection_lost(exc=None)
     self.assertEqual(0, len(self.manager.connections))
     self.assertEqual(0, len(self.manager.miners))
    def test_miner_method_subscribe_valid_address(self):
        conn = StratumProtocol(self.manager)
        transport = Mock()
        conn.connection_made(transport=transport)
        conn.send_error = MagicMock(return_value=None)

        params = {
            'address': 'HVZjvL1FJ23kH3buGNuttVRsRKq66WHUVZ'
        }
        conn.method_subscribe(params=params, msgid=None)
        conn.send_error.assert_not_called()
        transport.close.assert_not_called()
    def test_miner_method_subscribe_invalid_address2(self):
        conn = StratumProtocol(self.manager)
        transport = Mock()
        conn.connection_made(transport=transport)
        conn.send_error = MagicMock(return_value=None)

        params = {
            'address': 'ZiCa'
        }
        conn.method_subscribe(params=params, msgid=None)
        conn.send_error.assert_called_once()
        transport.close.assert_called_once()
class DifficultyTestCase(unittest.TestCase):
    def setUp(self):
        self.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self.loop)

        manager = MagicMock()
        transport = MagicMock()
        self.protocol = StratumProtocol(manager)
        self.protocol.connection_made(transport)
        self.protocol.current_job = MinerBlockJob(BLOCK_DATA_1, 0)

    def test_estimator_no_job(self):
        self.protocol.current_job = None
        self.loop.run_until_complete(self.protocol.estimator_loop())

    def test_estimator_empty(self):
        self.loop.run_until_complete(self.protocol.estimator_loop())

    def test_estimator_one_work(self):
        now = time.time()
        self.protocol._submitted_work.append(SubmittedWork(now, 25.0, 8))
        self.loop.run_until_complete(self.protocol.estimator_loop())

    def test_estimator_fixed_weight(self):
        now = time.time()
        hashpower = 2**40
        for _ in range(200):
            weight = self.protocol.current_weight
            geometric_p = 2**(-weight)
            trials = numpy.random.geometric(geometric_p)
            dt = 1.0 * trials / hashpower
            self.protocol._submitted_work.append(
                SubmittedWork(now + dt, weight, dt))
            self.loop.run_until_complete(self.protocol.estimator_loop())
            print('!! hashrate_ghs:', self.protocol.hashrate_ghs)
            now += dt
 def __call__(self) -> StratumProtocol:
     """Return an instance of StratumProtocol for a new connection."""
     return StratumProtocol(self)