Esempio n. 1
0
    def test_on_peer_error_during_connection(self):
        peer = Mock(is_online=True, connected=False, _errors=[])
        peer.add_error = lambda *x: peer._errors.append(x[0]) if x else peer._errors.append(int(time.time()))
        self.network_checker.return_value = async_coro(False)
        self.loop.run_until_complete(self.sut.on_peer_error(peer, error_type='connect'))
        self.assertEqual(len(peer._errors), 0)

        self.network_checker.return_value = async_coro(True)
        self.loop.run_until_complete(self.sut.on_peer_error(peer, error_type='connect'))
        self.assertEqual(len(peer._errors), 1)
Esempio n. 2
0
 def test_call_missing_response(self):
     conn = Mock(connected=True, protocol=True, score=10)
     conn2 = Mock(connected=True, protocol=True, score=10)
     conn.rpc_call.return_value = async_coro(None)
     conn2.rpc_call.return_value = async_coro(None)
     self.sut._connections = [conn, conn2]
     with self.assertRaises(exceptions.ElectrodMissingResponseException):
         self.loop.run_until_complete(
             self.sut.call('cafe', 'babe', agreement=2)
         )
Esempio n. 3
0
    def test_call_success(self):
        response = 'some response'
        conn = Mock(connected=True, protocol=True, score=10)
        self.sut._connections = [conn]
        conn.rpc_call.return_value = async_coro(response)
        res = self.loop.run_until_complete(self.sut.call('cafe', 'babe'))
        self.assertEqual(res, response)

        conn.rpc_call.return_value = async_coro(response)
        peer, res = self.loop.run_until_complete(self.sut.call('cafe', 'babe', get_peer=True))
        self.assertEqual(peer, conn)
        self.assertEqual(res, response)
Esempio n. 4
0
 def test_connect_ok(self):
     callback = Mock()
     callback_blocks = Mock()
     self.sut.add_on_blocks_callback(callback_blocks)
     self.sut.add_on_connect_callback(callback)
     reader, writer = Mock(), Mock()
     self.peer_factory().perform_handshake.return_value = async_coro('the peer version answer')
     self.connector.return_value = async_coro((reader, writer))
     self.peer_factory().next_message.return_value = async_coro(None)
     self.loop.run_until_complete(self.sut.connect())
     self.assertEqual(self.sut._version, 'the peer version answer')
     self.assertEqual(len(self.loopmock.method_calls), 1)
     Mock.assert_not_called(callback_blocks)
     self.assertTrue(self.sut.connected)
    def test_getrawtransaction_verbose_in_block_invalid_pow(self):
        header_hex = '010000006fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000982051' \
                     'fd1e4ba744bbbe680e1fee14677ba1a3c3540bf7b1cdb606e857233e0e61bc6649ffff001d01e36299'
        block_json = {
            "hash": "00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048",
            "height": 1,
            "version": 1,
            "versionHex": "",
            "merkleroot": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098",
            "time": 1231469665,
            "mediantime": 1231469665,
            "nonce": 2573394689,
            "bits": 486604799,
            "difficulty": 0,
            'chainwork': '00' * 32,
            "previousblockhash": "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
            "nextblockhash": "000000006a625f06636b8bb6ac7b960a8d03705d1ace08b1a19da3fdcc99ddbd",
            "tx": [
                "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098"
            ]
        }
        self.repository.headers.get_best_header.return_value = {'block_height': 513980}
        self.repository.headers.get_block_header.return_value = {
            'block_hash': block_json['hash'],
            'block_height': block_json['height'],
            'header_bytes': binascii.unhexlify(header_hex.encode()),
            'next_block_hash': block_json['nextblockhash']
        }
        self.repository.get_block_header.return_value = self.header
        self.repository.blockchain.get_json_transaction.return_value = None
        tx = {
            'hex': '01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff00'
                   '1d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7'
                   '947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000',

            'blockhash': '00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048',
            'confirmations': 6,
            'vout': []
        }
        self.repository.get_best_header.return_value = {'block_height': 513980}
        self.electrod.getrawtransaction.return_value = async_coro(tx)
        self.electrod.get_merkleproof.return_value = async_coro({'block_height': 1, 'merkle': ['ff' * 32], 'pos': 0})
        with self.assertRaises(InvalidPOWException):
            self.loop.run_until_complete(
                self.sut.getrawtransaction(
                    '0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098',
                    verbose=True
                )
            )
Esempio n. 6
0
    def test_sendrawtransaction_success(self):
        self.vo_service.sendrawtransaction.side_effect = [
            async_coro(
                'bedf6b43cf9a9278b8637d89f378a8f25b8f0e1be729325f7eea74a3096d9520'
            )
        ]

        async def test():
            await self.sut.start()
            response = await self.client.call('sendrawtransaction',
                                              params=['cafebabe'])
            return response

        res = self.loop.run_until_complete(test())
        self.assertEqual(
            res, {
                'error':
                None,
                'id':
                1,
                'jsonrpc':
                '2.0',
                'result':
                'bedf6b43cf9a9278b8637d89f378a8f25b8f0e1be729325f7eea74a3096d9520'
            })
Esempio n. 7
0
    def test_getblockheader_error_params(self):
        response = None
        self.vo_service.getblockheader.return_value = async_coro(response)

        async def test():
            await self.sut.start()
            response1 = await self.client.call('getblockheader', params=['wrong_blockhash'])
            response2 = await self.client.call('getblockheader')
            return response1, response2

        res, res2 = self.loop.run_until_complete(test())
        self.assertEqual(
            res,
            {
                'jsonrpc': '2.0',
                'error': {
                    'code': -5, 'message': 'Error parsing JSON:wrong_blockhash'
                },
                'id': 1,
                'result': None
            }
        )

        # Really should be code: -32602, but that'll cause bitcoin-cli not to
        # error out correctly, so we use -1 instead
        self.assertEqual(
            res2,
            {'jsonrpc': '2.0', 'error': {'code': -1, 'message': 'Invalid params'}, 'id': 1, 'result': None}
        )
        Mock.assert_not_called(self.vo_service.getblockheader)
 def test_check_new_header_same_header(self):
     """
     test on fallback method check_headers
     no new header received
     """
     header_timestamp = int(time.time()) - 100
     loc_header = net_header = {
         "block_height": 1,
         "block_hash": "ff" * 32,
         "timestamp": header_timestamp - 700,
         'header_bytes': b'',
         'prev_block_hash': '00' * 32
     }
     peer = Mock(server_info='mock_peer')
     self.interface.get_header.side_effect = [
         async_coro((peer, net_header))
     ]
     self.sut.synced = True
     self.sut.set_last_processed_header(loc_header)
     self.assertFalse(self.sut.lock.locked())
     self.loop.run_until_complete(self.sut.check_headers())
     Mock.assert_called_once_with(self.delay_task_runner,
                                  coro_call('check_headers'),
                                  in_range(655, 660))
     Mock.assert_has_calls(self.interface.get_header,
                           calls=[
                               call(2,
                                    fail_silent_out_of_range=True,
                                    get_peer=True),
                           ],
                           any_order=True)
     self.assertEqual(1, len(self.interface.method_calls))
     self.assertEqual(1, len(self.electrod_loop.method_calls))
     self.assertEqual(0, len(self.repo.method_calls))
    def test_no_new_network_best_header(self):
        """
        test reactor.check_headers method
        interface didn't returned any best header. will try again in
        """
        header_timestamp = int(
            time.time()) - self.sut.new_headers_fallback_poll_interval - 1
        loc_header = {
            "block_height": 1,
            "block_hash": "ff" * 32,
            "timestamp": header_timestamp
        }
        self.interface.get_header.return_value = async_coro(None)
        self.sut.synced = True
        self.sut.set_last_processed_header(loc_header)
        self.loop.run_until_complete(self.sut.check_headers())
        self.assertFalse(self.sut.lock.locked())

        Mock.assert_called_once_with(self.delay_task_runner,
                                     coro_call('check_headers'), 660)
        Mock.assert_called_with(self.interface.get_header,
                                2,
                                fail_silent_out_of_range=True,
                                get_peer=True)
        Mock.assert_called_once_with(self.electrod_loop.create_task,
                                     self.delay_task_runner())

        self.assertEqual(1, len(self.interface.method_calls))
        self.assertEqual(1, len(self.electrod_loop.method_calls))
        self.assertEqual(0, len(self.repo.method_calls))
    def test_on_new_headers_new_header(self):
        """
        test on fallback method check_headers
        new header received
        """
        header_timestamp = int(time.time()) - 100
        loc_header = {
            "block_height": 1,
            "block_hash": "ff" * 32,
            "timestamp": header_timestamp - 700,
            'header_bytes': b'',
            'prev_block_hash': '00' * 32
        }
        net_header = {
            "block_height": 2,
            "block_hash": "aa" * 32,
            "timestamp": header_timestamp,
            'header_bytes': b'',
            'prev_block_hash': 'ff' * 32
        }
        self.interface.get_header.side_effect = [async_coro(net_header)]
        self.sut.synced = True
        self.sut.set_last_processed_header(loc_header)
        self.assertFalse(self.sut.lock.locked())
        peer = Mock(server_info='mock_peer')
        self.repo.get_best_header.return_value = loc_header
        self.repo.save_header.side_effect = lambda a, b, c, d: True

        self.loop.run_until_complete(self.sut.on_new_header(peer, net_header))
        self.assertEqual(self.repo.get_best_header.call_count, 1)
        Mock.assert_called_once_with(self.repo.save_header,
                                     net_header['block_hash'],
                                     net_header['block_height'],
                                     net_header['header_bytes'],
                                     net_header['prev_block_hash'])
    def test_received_new_single_header(self):
        """
        test reactor.on_header method

        header ff*32 is saved at height 2020
        received a new header at height 2021 with hash aa*32
        header is saved to disk
        best header is updated at height 2021
        """
        self.sut.synced = False
        peer = Mock(server_info='mock_peer')
        loc_header = {'block_height': 2020, 'block_hash': 'ff' * 32}
        net_header = {
            'block_height': 2021,
            'block_hash': 'aa' * 32,
            'prev_block_hash': 'ff' * 32,
            'header_bytes': b''
        }
        self.interface.get_header.return_value = async_coro(net_header)

        self.repo.get_best_header.return_value = loc_header

        self.loop.run_until_complete(self.sut.on_new_header(peer, net_header))
        Mock.assert_called_once_with(self.repo.get_best_header)
        Mock.assert_called_once_with(self.repo.save_header,
                                     net_header['block_hash'],
                                     net_header['block_height'],
                                     net_header['header_bytes'],
                                     net_header['prev_block_hash'])
        self.assertEqual(0, len(self.interface.method_calls))
        self.assertEqual(0, len(self.electrod_loop.method_calls))
        self.assertEqual(2, len(self.repo.method_calls))
    def test_network_header_behind(self):
        """
        test reactor.on_header method

        network header behind: remote peer outdated, skip
        """
        self.sut.synced = True
        now = int(time.time())
        net_header = {
            'block_height': 1,
            'block_hash': 'aa' * 32,
            'timestamp': now - self.sut.new_headers_fallback_poll_interval + 10
        }
        loc_header = {
            'block_height': 2,
            'block_hash': 'ff' * 32,
            'timestamp': now - self.sut.new_headers_fallback_poll_interval + 10
        }
        peer = Mock(server_info='mock_peer')
        peer.close.return_value = True
        self.repo.get_best_header.return_value = loc_header
        self.repo.get_header_at_height.return_value = net_header
        self.interface.disconnect_from_peer.return_value = async_coro(True)
        self.loop.run_until_complete(self.sut.on_new_header(peer, net_header))

        Mock.assert_called_once_with(self.repo.get_header_at_height, 1)
        self.assertEqual(1, len(self.interface.method_calls))
        self.assertEqual(0, len(self.electrod_loop.method_calls))
        self.assertEqual(2, len(self.repo.method_calls))
Esempio n. 13
0
    def test_call_failure_not_enough_responses(self):
        response = 'some response'
        conn = Mock(connected=True, protocol=True, score=10)
        conn.rpc_call.return_value = async_coro(response)
        conn2 = Mock(connected=True, protocol=True, score=10)
        conn2.rpc_call.return_value = async_coro(None)
        self.sut._connections = [conn, conn2]
        with self.assertRaises(exceptions.ElectrodMissingResponseException):
            self.loop.run_until_complete(
                self.sut.call('cafe', 'babe', agreement=2))

        conn.rpc_call.return_value = async_coro(response)
        conn2.rpc_call.return_value = async_coro(None)
        self.assertIsNone(
            self.loop.run_until_complete(
                self.sut.call('cafe', 'babe', agreement=2, fail_silent=True)))
Esempio n. 14
0
    def test_connection_error(self):
        transport, protocol = Mock(), Mock()
        self.mock_loop.create_connection.return_value = async_coro(
            (transport, protocol))

        with self.assertRaises(ConnectionRefusedError) as e:
            self.loop.run_until_complete(self.sut.connect(self.server_info))
Esempio n. 15
0
    def test_getrawtransaction_success(self):
        self.vo_service.getrawtransaction.side_effect = [
            async_coro('cafebabe')
        ]

        async def test():
            await self.sut.start()
            response = await self.client.call('getrawtransaction',
                                              params=['00' * 32])
            response2 = await self.client.call('getrawtransaction',
                                               params=['00' * 32, True])
            return response, response2

        res, res2 = self.loop.run_until_complete(test())
        self.assertEqual(res, {
            'error': None,
            'id': 1,
            'jsonrpc': '2.0',
            'result': 'cafebabe'
        })
        self.assertEqual(
            res2, {
                'error': {
                    'code': -8,
                    'message': 'spruned error: Verbose mode not supported'
                },
                'id': 1,
                'jsonrpc': '2.0',
                'result': None
            })
        Mock.assert_has_calls(self.vo_service.getrawtransaction,
                              calls=[call('00' * 32, False)])
Esempio n. 16
0
    def test_getblock_error_error_params(self):
        response = None
        self.vo_service.getblockhash.return_value = async_coro(response)

        async def test():
            await self.sut.start()
            response1 = await self.client.call('getblockhash',
                                               params=['non_int'])
            response2 = await self.client.call('getblockhash')
            return response1, response2

        res, res2 = self.loop.run_until_complete(test())
        self.assertEqual(
            res, {
                'jsonrpc': '2.0',
                'error': {
                    'code': -5,
                    'message': 'Error parsing JSON:non_int'
                },
                'id': 1,
                'result': None
            })
        self.assertEqual(
            res2, {
                'jsonrpc': '2.0',
                'error': {
                    'code': -32602,
                    'message': 'Invalid params'
                },
                'id': 1,
                'result': None
            })
        Mock.assert_not_called(self.vo_service.getblock)
Esempio n. 17
0
 def test_estimatefee(self):
     self.electrod.estimatefee.side_effect = [
         ElectrodMissingResponseException(),
         async_coro(3)
     ]
     res = self.loop.run_until_complete(self.sut.estimatefee(6))
     self.assertEqual(res, 3)
Esempio n. 18
0
    def test_connect_success(self):
        self.sut.loop = self.loop
        self.network_checker.return_value = True
        conn1 = Mock(connected=False, score=0)
        conn1.connect = lambda: connect(conn1)
        conn2 = Mock(connected=False, score=0)
        conn2.connect = lambda: connect(conn2)
        conn3 = Mock(connected=False, score=0)
        conn3.connect = lambda: connect(conn3)
        self.connection_factory.side_effect = [conn1, conn2, conn3]
        on_connected_observer = Mock()
        on_connected_observer.return_value = async_coro(True)
        self.sut.add_on_connected_observer(on_connected_observer)
        self.loop.run_until_complete(
            asyncio.gather(self.stop_keepalive(7), self.sut.connect()))
        self.sut.loop = self.electrod_loop

        for conn in [conn1, conn2, conn3]:
            self.assertEqual(conn.add_on_connect_callback.call_count, 1)
            self.assertEqual(conn.add_on_header_callbacks.call_count, 1)
            self.assertEqual(conn.add_on_peers_callback.call_count, 1)
            self.assertEqual(conn.add_on_error_callback.call_count, 1)
            self.assertTrue(conn.connected)
        self.assertEqual(on_connected_observer.call_count, 1)
        self.assertEqual(3, len(self.sut.connections))
        self.assertEqual(3, len(self.sut.established_connections))
Esempio n. 19
0
 def test_gettxout(self):
     tx = '01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff00' \
          '1d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7' \
          '947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000'
     self.repository.get_best_header.return_value = {'block_height': 513980}
     self.electrod.getrawtransaction.return_value = async_coro(tx)
     self.repository.blockchain.get_transaction.return_value = None
     self.electrod.listunspents_by_scripthash.side_effect = [
         ElectrodMissingResponseException,
         async_coro([{
             'tx_hash':
             '0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098',
             'tx_pos': 0,
             'height': 0,
             'value': 1
         }])
     ]
     self.repository.headers.get_best_header.return_value = {
         'block_height':
         513980,
         'block_hash':
         '0000000000000000001a0822fbaef92ef048967fa32c68f96e3d57d13183ef2b'
     }
     res = self.loop.run_until_complete(
         self.sut.gettxout(
             '0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098',
             0))
     self.assertEqual(
         res, {
             "bestblock":
             "0000000000000000001a0822fbaef92ef048967fa32c68f96e3d57d13183ef2b",
             "confirmations": 513981,
             "value": "0.00000001",
             "scriptPubKey": {
                 "asm":
                 "",
                 "hex":
                 "410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7"
                 "589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac",
                 "reqSigs":
                 0,
                 "type":
                 "",
                 "addresses": []
             }
         })
Esempio n. 20
0
    def test_connect_ok(self):
        async def parallel():
            await asyncio.sleep(3)
            for peer in self.peers:
                self.sut.add_peer(peer)

            await asyncio.sleep(5)
            self.sut._keepalive = False

        self.online_checker.side_effect = [async_coro(False), async_coro(True)]
        self.loop.run_until_complete(
            asyncio.gather(parallel(), self.sut.connect()))
        Mock.assert_has_calls(self.loopmock.create_task,
                              calls=[
                                  call(coro_call('_connect_peer')),
                                  call(coro_call('_connect_peer'))
                              ])
Esempio n. 21
0
    def test_call_failure_disagreement_on_responses(self):
        response = 'some response'
        response2 = 'another response'
        conn = Mock(connected=True, protocol=True, score=10)
        conn.rpc_call.return_value = async_coro(response)
        conn2 = Mock(connected=True, protocol=True, score=10)
        conn2.rpc_call.return_value = async_coro(response2)
        self.sut._connections = [conn, conn2]
        with self.assertRaises(exceptions.NoQuorumOnResponsesException):
            self.loop.run_until_complete(
                self.sut.call('cafe', 'babe', agreement=2))

        conn.rpc_call.return_value = async_coro(response)
        conn2.rpc_call.return_value = async_coro(response2)
        self.assertIsNone(
            self.loop.run_until_complete(
                self.sut.call('cafe', 'babe', agreement=2, fail_silent=True)))
Esempio n. 22
0
    def test_check_blockchain_local_a_lot_behind(self):
        """
        something bad happened around block 16, we saved it, we didn't tracked it and we start over 5 blocks later.
        also, the last block tracked by the blockheader reactor was stuck ad block 9.
        basically, everything is screwed up, but we recover and download the needed blocks.
        """
        self.sut.set_last_processed_block({'block_hash': 'cafe', 'block_height': 9})
        self.repo.headers.get_best_header.return_value = {'block_hash': 'babe', 'block_height': 20}
        self.interface.get_blocks.return_value = async_coro(
            {
                'block17': {'block_hash': 'block17', 'block_bytes': b'raw'},
                'block18': {'block_hash': 'block18', 'block_bytes': b'raw'},
                'block19': {'block_hash': 'block19', 'block_bytes': b'raw'},
                'block20': {'block_hash': 'block20', 'block_bytes': b'raw'}
            }
        )
        self.repo.headers.get_headers_since_height.return_value = [
            {'block_hash': 'block16', 'block_height': 16},
            {'block_hash': 'block17', 'block_height': 17},
            {'block_hash': 'block18', 'block_height': 18},
            {'block_hash': 'block19', 'block_height': 19},
            {'block_hash': 'block20', 'block_height': 20}
        ]
        self.repo.blockchain.get_block.side_effect = [
            {'block_hash': 'block16', 'block_bytes': b'raw'}, None, None, None, None
        ]
        self.repo.blockchain.save_blocks.side_effect = [
            {'block_hash': 'block17', 'block_bytes': b'raw'},
            {'block_hash': 'block18', 'block_bytes': b'raw'},
            {'block_hash': 'block19', 'block_bytes': b'raw'},
            {'block_hash': 'block20', 'block_bytes': b'raw'}
        ]
        self.repo.blockchain.save_blocks.side_effect = lambda *x: x

        self.loop.run_until_complete(self.sut.check())

        Mock.assert_called_once_with(self.repo.headers.get_best_header)
        Mock.assert_called_once_with(self.repo.headers.get_headers_since_height, 15, limit=10)
        Mock.assert_has_calls(
            self.repo.blockchain.get_block,
            calls=[
                call('block16'),
                call('block17'),
                call('block18'),
                call('block19'),
                call('block20')
            ]
        )
        Mock.assert_called_once_with(self.interface.get_blocks, 'block17', 'block18', 'block19', 'block20')

        Mock.assert_called_once_with(
            self.repo.blockchain.save_blocks,
            {'block_hash': 'block17', 'block_bytes': b'raw'},
            {'block_hash': 'block18', 'block_bytes': b'raw'},
            {'block_hash': 'block19', 'block_bytes': b'raw'},
            {'block_hash': 'block20', 'block_bytes': b'raw'}
        )
        self.assertEqual(self.sut._last_processed_block, {'block_hash': 'block20', 'block_height': 20})
    def test_local_db_behind_100_headers(self):
        """
        test reactor.on_new_header

        header ff*32 is saved at height 2020
        received a new header at height 2120 with hash aa*32
        chunk from header 2016 is requested
        headers from 2021 to 2120 are saved in the db
        best header is updated at height 2120
        :return:
        """
        header_timestamp = int(time.time())
        peer = Mock(server_info='mock_peer')
        loc_header = {
            "block_height": 2020,
            "block_hash": "ff" * 32,
            "timestamp": header_timestamp - 6000
        }
        net_header = {
            "block_height": 2120,
            "block_hash": "aa" * 32,
            "timestamp": header_timestamp
        }
        self.sut.synced = True
        self.sut.set_last_processed_header(loc_header)
        self.repo.get_best_header.return_value = loc_header
        _headers = make_headers(2017, 2120, '00' * 32)
        self.interface.get_headers_in_range_from_chunks.side_effect = [
            async_coro((Mock(), _headers)),
            async_coro(None)
        ]
        self.interface.get_header.return_value = async_coro(net_header)
        self.repo.save_headers.side_effect = lambda x, **k: x

        self.loop.run_until_complete(self.sut.on_new_header(peer, net_header))

        Mock.assert_called_with(
            self.repo.save_headers,
            [h for h in _headers if h['block_height'] > 2020])
        Mock.assert_not_called(peer.close)
        self.assertEqual(self.sut._last_processed_header, _headers[-1])
        self.assertEqual(self.sut.synced, True)
        self.assertEqual(1, len(self.interface.method_calls))
        self.assertEqual(2, len(self.repo.method_calls))
        self.assertEqual(0, len(self.electrod_loop.method_calls))
Esempio n. 24
0
    def test_mempool_observer(self):
        connection = Mock()
        from pycoin.tx.Tx import Tx
        tx = Tx.from_hex(
            '01000000000101112a649fd72656cf572259cb7cb61bd31ccdbdf0944070e73401565affbe629d0100000000ffffffff02608'
            'de2110000000017a914d52b516c1a094462959ed6facebb94429d2cebf487d3135b0b00000000220020701a8d401c84fb13e6'
            'baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d0400473044022006b149e0cf031f57fd443bd1210b381e9b1b15094'
            '57ba1f49e48b803696f56e802203d66bd974ad3ac5b7591cc84e706b78d139c61e2bf1995a89c4dc0758984a2b70148304502'
            '2100fe7275d601080e1870517774a3ad6accaa7f8ad144addec3251e98685d4fefad02207792c2b0ed6ab42ed2ba6d12e6bd3'
            '4db8c6f4ac6f15e604f70ea85a735c450b1016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd'
            '92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e'
            '046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae00000000')
        self.loop.run_until_complete(
            self.sut.on_transaction(connection, {'tx': tx}))
        self.assertEqual(tx.w_id(),
                         [x for x in self.mempool_repository.get_txids()][0])
        self.repository.blockchain.get_transactions_by_block_hash.return_value = [], None

        block = Block(1,
                      b'0' * 32,
                      merkle_root=merkle([tx.hash()]),
                      timestamp=123456789,
                      difficulty=3000000,
                      nonce=1 * 137)
        block.txs.append(tx)
        as_bin = block.as_bin()
        Block.from_bin(as_bin)
        block_header = {'block_hash': block.id()}
        self.batcher_factory.add_peer.return_value = async_coro(True)
        self.batcher_factory.inv_item_to_future.return_value = block.as_bin()
        mempool_response = self.mempool_repository.get_raw_mempool(True)

        self.assertEqual(
            {
                '41867301a6cff5c47951aa1a4eef0be910db0cb5f154eaeb469732e1f9b54548':
                {
                    'size': 381,
                    'fee': 0,
                    'modifiedfee': 0,
                    'time': ANY,
                    'height': 0,
                    'descendantcount': 0,
                    'descendantsize': 0,
                    'descendantfees': 0,
                    'ancestorcount': 0,
                    'ancestorsize': 0,
                    'ancestorfees': 0,
                    'depends': []
                }
            }, mempool_response)
        self.repository.blockchain.save_block.side_effect = lambda a: {
            'block_object': Block.from_bin(a['block_bytes'])
        }
        self.repository.blockchain.get_transactions_by_block_hash.return_value = [], None
        self.loop.run_until_complete(self.sut.on_block_header(block_header))
        self.assertEqual(self.mempool_repository.get_raw_mempool(True), {})
        self.assertEqual([x for x in self.mempool_repository.get_txids()], [])
 def test_getblock_p2p_non_verbose_network_error(self):
     self.repository.headers.get_best_header.return_value = {'block_height': 513980}
     self.repository.headers.get_block_header.return_value = self.header
     self.repository.blockchain.get_transactions_by_block_hash.return_value = [], None
     self.p2p.get_block.side_effect = lambda *a, **kw: async_coro(None)
     with self.assertRaises(ServiceException):
         self.loop.run_until_complete(
             self.sut.getblock('000000000000000000376267d342878f869cb68192ff5d73f5f1953ae83e3e1e', 0)
         )
    def test_on_new_headers_5_blocks_behind(self):
        """
        local height is 10
        remote height is 15
        5 headers are requested with interface.get_headers_in_range api (no chunks)
        due race conditions, two errors are triggered: no peers, empty response
        the third retry headers are fetched
        headers are saved
        best height is 15
        sync true
        """
        header_timestamp = int(time.time())
        net_header = {
            "block_height": 15,
            "block_hash": "55" * 32,
            "timestamp": header_timestamp,
            "prev_block_hash": "54" * 32,
            "header_bytes": b"0" * 80
        }
        peer = Mock(server_info='mock_peer')
        loc_header = {
            "block_height": 10,
            "block_hash": "bb" * 32,
            "timestamp": header_timestamp - 600 * 5,
            "prev_block_hash": "aa" * 32,
            "header_bytes": b"0" * 80
        }
        self.repo.get_best_header.return_value = loc_header
        headers = make_headers(11, 15, 'bb' * 32) + [net_header]

        self.interface.get_headers_in_range.side_effect = [
            exceptions.NoPeersException,
            async_coro(None),
            async_coro(headers),
        ]
        self.interface.get_header.return_value = async_coro(net_header)
        self.repo.save_headers.side_effect = lambda x, **k: x

        self.loop.run_until_complete(self.sut.on_new_header(peer, net_header))
        self.assertEqual(self.sut._last_processed_header, net_header)
        self.assertTrue(self.sut.synced)
        self.assertEqual(3, len(self.interface.method_calls))
        self.assertEqual(4, len(self.repo.method_calls))
        self.assertEqual(0, len(self.electrod_loop.method_calls))
Esempio n. 27
0
 def test_get_header_ok(self):
     peer = Mock()
     self.connectionpool.call.return_value = async_coro(
         (peer, self.electrum_header))
     res = self.loop.run_until_complete(self.sut.get_header(513526))
     self.assertEqual(res, self.parsed_header)
     bitcoind_header = "00000020fe52010fa7c798b97621508b772142dfc7b594df7a3a3200000000000000000097db2dc9" \
                       "4e2799bcdd7259f0876467b379fe44b69342df38a8ec2f350722f9a73367a95aa38955173732b883"
     self.assertEqual(binascii.unhexlify(bitcoind_header),
                      self.parsed_header['header_bytes'])
Esempio n. 28
0
 def test_callbacks(self):
     hcb = Mock(return_value=async_coro(True))
     ccb = Mock(return_value=async_coro(True))
     dcb = Mock(return_value=async_coro(True))
     pcb = Mock(return_value=async_coro(True))
     ecb = Mock(return_value=async_coro(True))
     self.sut.add_on_header_callbacks(hcb)
     self.sut.add_on_error_callback(ecb)
     self.sut.add_on_connect_callback(ccb)
     self.sut.add_on_disconnect_callback(dcb)
     self.sut.add_on_peers_callback(pcb)
     self.loop.run_until_complete(
         asyncio.gather(self.sut.on_header('header'), self.sut.on_connect(),
                        self.sut.on_error('error'), self.sut.on_peers()))
     self.sut.on_connectrum_disconnect()
     for m in [hcb, ccb, dcb, pcb]:
         Mock.assert_called_with(m, self.sut)
     Mock.assert_called_with(ecb, self.sut, error_type='error')
     self.assertEqual(self.sut.last_header, 'header')
Esempio n. 29
0
    def test_handle_peer_error_ping_timeout(self):
        conn = Mock(connected=True, score=10)
        conn.ping.return_value = async_coro(None)
        conn.disconnect.return_value = 'disconnect'
        self.delayer.return_value = 'delayer'

        res = self.loop.run_until_complete(self.sut._handle_peer_error(conn))
        self.assertIsNone(res)
        Mock.assert_called_with(self.electrod_loop.create_task, 'delayer')
        Mock.assert_called_with(self.delayer, 'disconnect')
 def test_get_block(self):
     block = b'block'
     self.pool.get.return_value = async_coro(block)
     response = self.loop.run_until_complete(self.sut.get_block('aa' * 32))
     self.assertEqual(
         response, {
             "block_hash": "aa" * 32,
             "header_bytes": b"block",
             "block_bytes": b"block"
         })