Exemple #1
0
    def test_block_sync_many_new_blocks(self):
        self._add_new_blocks(150)

        manager2 = self.create_peer(self.network)
        self.assertEqual(manager2.state, manager2.NodeState.READY)

        conn = FakeConnection(self.manager1, manager2)

        while not conn.is_empty():
            conn.run_one_step(debug=True)
            self.clock.advance(0.1)

        node_sync = conn.proto1.state.sync_manager
        self.assertEqual(node_sync.synced_timestamp, node_sync.peer_timestamp)
        self.assertTipsEqual(self.manager1, manager2)
        self.assertConsensusEqual(self.manager1, manager2)
        self.assertConsensusValid(self.manager1)
        self.assertConsensusValid(manager2)
Exemple #2
0
    def test_mempool_basic(self):
        # 10 blocks
        self._add_new_blocks(2)
        # N blocks to unlock the reward
        add_blocks_unlock_reward(self.manager1)

        # 5 transactions to be confirmed by the next blocks
        self._add_new_transactions(5)
        # 2 more blocks
        self._add_new_blocks(2)
        # 30 transactions in the mempool
        self._add_new_transactions(30)

        debug_pdf = False
        if debug_pdf:
            dot1 = GraphvizVisualizer(self.manager1.tx_storage,
                                      include_verifications=True,
                                      include_funds=True).dot()
            dot1.render('mempool-test')

        manager2 = self.create_peer(self.network, enable_sync_v1=True)
        self.assertEqual(manager2.state, manager2.NodeState.READY)

        conn = FakeConnection(self.manager1, manager2)
        for _ in range(1000):
            if conn.is_empty():
                break
            conn.run_one_step(debug=True)
            self.clock.advance(1)

        self.assertConsensusValid(self.manager1)
        self.assertConsensusValid(manager2)
        self.assertConsensusEqual(self.manager1, manager2)

        # 3 genesis
        # 25 blocks
        # Unlock reward blocks
        # 8 txs
        self.assertEqual(len(manager2.tx_storage.indexes.mempool_tips.get()),
                         1)
        self.assertEqual(
            len(self.manager1.tx_storage.indexes.mempool_tips.get()), 1)
Exemple #3
0
class BaseHathorSyncMethodsTestCase(unittest.TestCase):
    __test__ = False

    def setUp(self):
        super().setUp()

        # import sys
        # from twisted.python import log
        # log.startLogging(sys.stdout)

        self.network = 'testnet'
        self.manager1 = self.create_peer(self.network, unlock_wallet=True)
        self.manager1.avg_time_between_blocks = 4

        self.genesis = self.manager1.tx_storage.get_all_genesis()
        self.genesis_blocks = [tx for tx in self.genesis if tx.is_block]

    def _add_new_tx(self, address, value):
        from hathor.transaction import Transaction
        from hathor.wallet.base_wallet import WalletOutputInfo

        outputs = []
        outputs.append(
            WalletOutputInfo(address=decode_address(address),
                             value=int(value),
                             timelock=None))

        tx = self.manager1.wallet.prepare_transaction_compute_inputs(
            Transaction, outputs, self.manager1.tx_storage)
        tx.timestamp = int(self.clock.seconds())
        tx.storage = self.manager1.tx_storage
        tx.weight = 10
        tx.parents = self.manager1.get_new_tx_parents()
        tx.resolve()
        tx.verify()
        self.manager1.propagate_tx(tx)
        self.clock.advance(10)
        return tx

    def _add_new_transactions(self, num_txs):
        txs = []
        for _ in range(num_txs):
            address = self.get_address(0)
            value = random.choice([5, 10, 50, 100, 120])
            tx = self._add_new_tx(address, value)
            txs.append(tx)
        return txs

    def _add_new_block(self, propagate=True):
        block = self.manager1.generate_mining_block()
        self.assertTrue(block.resolve())
        block.verify()
        self.manager1.on_new_tx(block, propagate_to_peers=propagate)
        self.clock.advance(10)
        return block

    def _add_new_blocks(self, num_blocks, propagate=True):
        blocks = []
        for _ in range(num_blocks):
            blocks.append(self._add_new_block(propagate=propagate))
        return blocks

    def test_get_blocks_before(self):
        genesis_block = self.genesis_blocks[0]
        result = self.manager1.tx_storage.get_blocks_before(genesis_block.hash)
        self.assertEqual(0, len(result))

        genesis_tx = [tx for tx in self.genesis if not tx.is_block][0]
        with self.assertRaises(TransactionIsNotABlock):
            self.manager1.tx_storage.get_blocks_before(genesis_tx.hash)

        blocks = self._add_new_blocks(20)
        num_blocks = 5

        for i, block in enumerate(blocks):
            result = self.manager1.tx_storage.get_blocks_before(
                block.hash, num_blocks=num_blocks)

            expected_result = [genesis_block] + blocks[:i]
            expected_result = expected_result[-num_blocks:]
            expected_result = expected_result[::-1]
            self.assertEqual(result, expected_result)

    def test_block_sync_only_genesis(self):
        manager2 = self.create_peer(self.network)
        self.assertEqual(manager2.state, manager2.NodeState.READY)

        conn = FakeConnection(self.manager1, manager2)

        conn.run_one_step()  # HELLO
        conn.run_one_step()  # PEER-ID
        conn.run_one_step()  # READY

        node_sync = conn.proto1.state.sync_manager
        self.assertEqual(node_sync.synced_timestamp, node_sync.peer_timestamp)
        self.assertTipsEqual(self.manager1, manager2)

    def test_block_sync_new_blocks(self):
        self._add_new_blocks(15)

        manager2 = self.create_peer(self.network)
        self.assertEqual(manager2.state, manager2.NodeState.READY)

        conn = FakeConnection(self.manager1, manager2)

        for _ in range(10000):
            if conn.is_empty():
                break
            conn.run_one_step(debug=True)
            self.clock.advance(0.1)

        node_sync = conn.proto1.state.sync_manager
        self.assertEqual(node_sync.synced_timestamp, node_sync.peer_timestamp)
        self.assertTipsEqual(self.manager1, manager2)
        self.assertConsensusEqual(self.manager1, manager2)
        self.assertConsensusValid(self.manager1)
        self.assertConsensusValid(manager2)

    def test_block_sync_many_new_blocks(self):
        self._add_new_blocks(150)

        manager2 = self.create_peer(self.network)
        self.assertEqual(manager2.state, manager2.NodeState.READY)

        conn = FakeConnection(self.manager1, manager2)

        while not conn.is_empty():
            conn.run_one_step(debug=True)
            self.clock.advance(0.1)

        node_sync = conn.proto1.state.sync_manager
        self.assertEqual(node_sync.synced_timestamp, node_sync.peer_timestamp)
        self.assertTipsEqual(self.manager1, manager2)
        self.assertConsensusEqual(self.manager1, manager2)
        self.assertConsensusValid(self.manager1)
        self.assertConsensusValid(manager2)

    def test_block_sync_new_blocks_and_txs(self):
        self._add_new_blocks(25)
        self._add_new_transactions(3)
        self._add_new_blocks(4)
        self._add_new_transactions(5)

        manager2 = self.create_peer(self.network)
        self.assertEqual(manager2.state, manager2.NodeState.READY)

        conn = FakeConnection(self.manager1, manager2)

        for _ in range(1000):
            conn.run_one_step()
            self.clock.advance(0.1)

        # dot1 = self.manager1.tx_storage.graphviz(format='pdf')
        # dot1.render('dot1')

        # dot2 = manager2.tx_storage.graphviz(format='pdf')
        # dot2.render('dot2')

        node_sync = conn.proto1.state.sync_manager
        self.assertEqual(self.manager1.tx_storage.latest_timestamp,
                         manager2.tx_storage.latest_timestamp)
        self.assertEqual(node_sync.synced_timestamp, node_sync.peer_timestamp)
        self.assertTipsEqual(self.manager1, manager2)
        self.assertConsensusEqual(self.manager1, manager2)
        self.assertConsensusValid(self.manager1)
        self.assertConsensusValid(manager2)

    def test_tx_propagation_nat_peers(self):
        """ manager1 <- manager2 <- manager3
        """
        self._add_new_blocks(25)

        self.manager2 = self.create_peer(self.network)
        self.conn1 = FakeConnection(self.manager1, self.manager2)

        for _ in range(1000):
            if self.conn1.is_empty():
                break
            self.conn1.run_one_step()
            self.clock.advance(0.1)
        self.assertTipsEqual(self.manager1, self.manager2)

        self._add_new_blocks(1)

        for _ in range(1000):
            if self.conn1.is_empty():
                break
            self.conn1.run_one_step()
            self.clock.advance(0.1)
        self.assertTipsEqual(self.manager1, self.manager2)

        self.manager3 = self.create_peer(self.network)
        self.conn2 = FakeConnection(self.manager2, self.manager3)

        for _ in range(1000):
            if self.conn1.is_empty() and self.conn2.is_empty():
                break
            self.conn1.run_one_step()
            self.conn2.run_one_step()
            self.clock.advance(0.1)

        self.assertTipsEqual(self.manager1, self.manager2)
        self.assertTipsEqual(self.manager1, self.manager3)

        self._add_new_transactions(1)

        for _ in range(1000):
            if self.conn1.is_empty() and self.conn2.is_empty():
                break
            self.conn1.run_one_step()
            self.conn2.run_one_step()
            self.clock.advance(0.1)

        self.assertTipsEqual(self.manager1, self.manager2)
        self.assertTipsEqual(self.manager1, self.manager3)
        self.assertConsensusEqual(self.manager1, self.manager2)
        self.assertConsensusEqual(self.manager1, self.manager3)
        self.assertConsensusValid(self.manager1)
        self.assertConsensusValid(self.manager2)
        self.assertConsensusValid(self.manager3)
    def test_split_brain(self):
        debug_pdf = False

        manager1 = self.create_peer(self.network, unlock_wallet=True)
        manager1.avg_time_between_blocks = 3

        manager2 = self.create_peer(self.network, unlock_wallet=True)
        manager2.avg_time_between_blocks = 3

        for _ in range(10):
            add_new_block(manager1, advance_clock=1)
            add_blocks_unlock_reward(manager1)
            add_new_block(manager2, advance_clock=1)
            add_blocks_unlock_reward(manager2)
            self.clock.advance(10)
            for _ in range(random.randint(3, 10)):
                add_new_transactions(manager1, random.randint(2, 4), advance_clock=1)
                add_new_transactions(manager2, random.randint(3, 7), advance_clock=1)
                add_new_double_spending(manager1)
                add_new_double_spending(manager2)
                self.clock.advance(10)
        self.clock.advance(20)

        if debug_pdf:
            dot1 = GraphvizVisualizer(manager1.tx_storage, include_verifications=True).dot()
            dot1.render('dot1-pre')

        self.assertTipsNotEqual(manager1, manager2)
        self.assertConsensusValid(manager1)
        self.assertConsensusValid(manager2)

        # input('Press enter to continue...')

        conn = FakeConnection(manager1, manager2)

        conn.run_one_step()  # HELLO
        conn.run_one_step()  # PEER-ID
        conn.run_one_step()  # READY
        conn.run_one_step()  # GET-PEERS
        conn.run_one_step()  # GET-TIPS
        conn.run_one_step()  # PEERS
        conn.run_one_step()  # TIPS

        empty_counter = 0
        for i in range(2000):
            if conn.is_empty():
                empty_counter += 1
                if empty_counter > 10:
                    break
            else:
                empty_counter = 0

            conn.run_one_step()
            self.clock.advance(0.2)

        if debug_pdf:
            dot1 = GraphvizVisualizer(manager1.tx_storage, include_verifications=True).dot()
            dot1.render('dot1-post')
            dot2 = GraphvizVisualizer(manager2.tx_storage, include_verifications=True).dot()
            dot2.render('dot2-post')

        node_sync = conn.proto1.state.sync_manager
        self.assertEqual(node_sync.synced_timestamp, node_sync.peer_timestamp)
        self.assertTipsEqual(manager1, manager2)
        self.assertConsensusEqual(manager1, manager2)
        self.assertConsensusValid(manager1)
        self.assertConsensusValid(manager2)