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_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)
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)