def test_handle_message_transaction(self, m_Transaction): """ This handler handles a MessageTransaction type Transaction. :param m_Transaction: :return: """ m_Transaction.from_pbdata.return_value = Mock( autospec=MessageTransaction, txhash=b'12345') self.channel.factory.master_mr.isRequested.return_value = True # Yes, this is a Message which we have requested self.channel.factory.buffered_chain.tx_pool.pending_tx_pool_hash = [ ] # No, we haven't processed this TX before mtData = qrl_pb2.Transaction() msg = make_message(func_name=qrllegacy_pb2.LegacyMessage.MT, mtData=mtData) P2PTxManagement.handle_message_transaction(self.channel, msg) self.channel.factory.add_unprocessed_txn.assert_called() # What if we ended up parsing a Transaction that we never requested in the first place? self.channel.factory.add_unprocessed_txn.reset_mock() self.channel.factory.master_mr.isRequested.return_value = False P2PTxManagement.handle_message_transaction(self.channel, msg) self.channel.factory.add_unprocessed_txn.assert_not_called()
def test_handle_message_received_ignores_unknown_message_types(self): mrData = qrllegacy_pb2.MRData(type=999) msg = make_message(func_name=qrllegacy_pb2.LegacyMessage.MR, mrData=mrData) P2PTxManagement.handle_message_received(self.channel, msg) self.channel.factory.request_full_message.assert_not_called()
def test_handle_slave_error_parsing_transaction(self, m_Transaction, m_logger): m_Transaction.from_pbdata.side_effect = Exception msg = make_message(func_name=qrllegacy_pb2.LegacyMessage.SL, slData=qrl_pb2.Transaction()) P2PTxManagement.handle_slave(self.channel, msg) self.channel.factory.add_unprocessed_txn.assert_not_called() m_logger.exception.assert_called() self.channel.loseConnection.assert_called()
def test_handle_message_received_ignores_messages_it_already_has(self): self.channel.factory.master_mr.contains.return_value = True mrData = qrllegacy_pb2.MRData(type=qrllegacy_pb2.LegacyMessage.SL) msg = make_message(func_name=qrllegacy_pb2.LegacyMessage.MR, mrData=mrData) P2PTxManagement.handle_message_received(self.channel, msg) self.channel.factory.request_full_message.assert_not_called()
def test_handle_message_received_transactions_ignored_while_unsynced(self): self.channel.factory.sync_state.state = ESyncState.syncing mrData = qrllegacy_pb2.MRData(type=qrllegacy_pb2.LegacyMessage.TX) msg = make_message(func_name=qrllegacy_pb2.LegacyMessage.MR, mrData=mrData) P2PTxManagement.handle_message_received(self.channel, msg) self.channel.factory.request_full_message.assert_not_called()
def test_handle_message_received_ignores_messages_it_already_has_requested( self): self.channel.factory.master_mr.contains.return_value = False # No, we don't have this message yet. self.channel.factory.master_mr.is_callLater_active.return_value = True # Yes, we have requested it. mrData = qrllegacy_pb2.MRData(type=qrllegacy_pb2.LegacyMessage.SL) msg = make_message(func_name=qrllegacy_pb2.LegacyMessage.MR, mrData=mrData) P2PTxManagement.handle_message_received(self.channel, msg) self.channel.factory.request_full_message.assert_not_called()
def test_handle_message_received_ignores_blocks(self): """ handle_message_received() should ignore MessageReceipts for blocks that are too far away from our current block height, or if it's an orphan block. """ self.channel.factory.chain_height = 10 # Right now, our node is on block 10. self.channel.factory.master_mr.contains.return_value = False # No, we do not already have this Message. self.channel.factory.master_mr.is_callLater_active.return_value = False # No, we haven't requested this Message yet. # Ignore blocks that are config.dev_max_margin_block_number ahead. mrData = qrllegacy_pb2.MRData(type=qrllegacy_pb2.LegacyMessage.BK, block_number=10 + config.dev.max_margin_block_number + 1) msg = make_message(func_name=qrllegacy_pb2.LegacyMessage.MR, mrData=mrData) P2PTxManagement.handle_message_received(self.channel, msg) self.channel.factory.request_full_message.assert_not_called() # Ignore blocks that are config.dev_min_margin_block_number behind msg.mrData.block_number = 2 P2PTxManagement.handle_message_received(self.channel, msg) self.channel.factory.request_full_message.assert_not_called() msg.mrData.block_number = 10 # Yes, it's another block 10! self.channel.factory.is_block_present.return_value = False # But we don't have its previous block. P2PTxManagement.handle_message_received(self.channel, msg) self.channel.factory.request_full_message.assert_not_called() msg.mrData.block_number = 11 # now we have a follow-up block. self.channel.factory.is_block_present.return_value = True # We do have its previous block. P2PTxManagement.handle_message_received(self.channel, msg) self.channel.factory.request_full_message.assert_called_once_with( msg.mrData)
def __init__(self, db_state: State, mining_address: bytes): self.start_time = time.time() self.db_state = db_state self._sync_state = SyncState() self.peer_manager = P2PPeerManager() self.peer_manager.load_peer_addresses() self.peer_manager.register(P2PPeerManager.EventType.NO_PEERS, self.connect_peers) self.p2pchain_manager = P2PChainManager() self.tx_manager = P2PTxManagement() self._chain_manager = None # FIXME: REMOVE. This is temporary self._p2pfactory = None # FIXME: REMOVE. This is temporary self._pow = None self.mining_address = mining_address banned_peers_filename = os.path.join(config.user.wallet_dir, config.dev.banned_peers_filename) self._banned_peers = ExpiringSet( expiration_time=config.user.ban_minutes * 60, filename=banned_peers_filename) reactor.callLater(10, self.monitor_chain_state)
def test_handle_message_transaction_invalid_transaction( self, m_Transaction, logger): """ If the Transaction was so malformed that parsing it caused an exception, the peer should be disconnected. :param m_Transaction: :param logger: :return: """ m_Transaction.from_pbdata.side_effect = Exception mtData = qrl_pb2.Transaction() msg = make_message(func_name=qrllegacy_pb2.LegacyMessage.MT, mtData=mtData) P2PTxManagement.handle_message_transaction(self.channel, msg) self.channel.loseConnection.assert_called()
def test_count_registrations(self): channel = Mock() channel.register = Mock() self.tx_manager = P2PTxManagement() self.tx_manager.new_channel(channel) channel.register.assert_called() self.assertEquals(8, channel.register.call_count)
def test_handle_full_message_request(self): """ A peer has requested a full message that corresponds to a MessageReceipt. This function checks if we actually have the full message for the given hash. If it does, send to peer, otherwise ignore. """ # We do have the Message the peer requested. mrData = qrllegacy_pb2.MRData(type=qrllegacy_pb2.LegacyMessage.SL) msg = make_message(func_name=qrllegacy_pb2.LegacyMessage.MR, mrData=mrData) P2PTxManagement.handle_full_message_request(self.channel, msg) self.channel.send.assert_called() # We don't have the Message the peer requested. self.channel.send.reset_mock() self.channel.factory.master_mr.get.return_value = None P2PTxManagement.handle_full_message_request(self.channel, msg) self.channel.send.assert_not_called()
def test_handle_message_received(self): """ handle_message_received() handles MessageReceipts. MessageReceipts are metadata for Messages, so peers know which peer has which blocks/transactions/whatever, but can request the full Message at their discretion. :return: """ mrData = qrllegacy_pb2.MRData(type=qrllegacy_pb2.LegacyMessage.SL) msg = make_message(func_name=qrllegacy_pb2.LegacyMessage.MR, mrData=mrData) # No, we do not already have this particular TX. self.channel.factory.master_mr.contains.return_value = False # No, we have not already requested the Message behind this MessageReceipt. self.channel.factory.master_mr.is_callLater_active.return_value = False P2PTxManagement.handle_message_received(self.channel, msg) self.channel.factory.request_full_message.assert_called_once_with( mrData)
def test_notification_no_observer(self): source = Mock() channel = Observable(source) self.tx_manager = P2PTxManagement() self.tx_manager.new_channel(channel) event = ObservableEvent("event_id") with self.assertRaisesRegexp(RuntimeError, "Observer not registered for"): channel.notify(event, force_delivery=True)
def test_handle_message_received_transactions_ignored_while_mempool_full( self, mock_logger): self.channel.factory.sync_state.state = ESyncState.synced self.channel.factory.master_mr.contains.return_value = False # No, we do not already have this Message. self.channel.factory.master_mr.is_callLater_active.return_value = False # No, we haven't requested this Message yet. # First, test when the mempool is NOT full self.channel.factory._chain_manager.tx_pool.is_full_pending_transaction_pool.return_value = False mrData = qrllegacy_pb2.MRData(type=qrllegacy_pb2.LegacyMessage.TX) msg = make_message(func_name=qrllegacy_pb2.LegacyMessage.MR, mrData=mrData) P2PTxManagement.handle_message_received(self.channel, msg) self.channel.factory.request_full_message.assert_called() # Now, test when the mempool IS full self.channel.factory.request_full_message.reset_mock() self.channel.factory._chain_manager.tx_pool.is_full_pending_transaction_pool.return_value = True P2PTxManagement.handle_message_received(self.channel, msg) self.channel.factory.request_full_message.assert_not_called()
def __init__(self, mining_address: bytes): self.start_time = ntp.getTime() self._sync_state = SyncState() self.peer_manager = P2PPeerManager() self.peer_manager.load_peer_addresses() self.p2pchain_manager = P2PChainManager() self.tx_manager = P2PTxManagement() self._chain_manager = None # FIXME: REMOVE. This is temporary self._p2pfactory = None # FIXME: REMOVE. This is temporary self._pow = None self.mining_address = mining_address reactor.callLater(10, self.monitor_chain_state)
def test_bad_tx(self): source = Mock() source.factory = Mock() source.factory.master_mr = Mock() source.factory.master_mr.isRequested = Mock() source.factory.add_unprocessed_txn = Mock() channel = Observable(source) self.tx_manager = P2PTxManagement() self.tx_manager.new_channel(channel) tx = SlaveTransaction.create([], [], 1, bytes(100)) event = qrllegacy_pb2.LegacyMessage(func_name=qrllegacy_pb2.LegacyMessage.TX, txData=tx.pbdata) channel.notify(event, force_delivery=True) source.factory.master_mr.isRequested.assert_not_called() source.factory.add_unprocessed_txn.assert_not_called()
def test_notification(self): source = Mock() source.factory = Mock() source.factory.master_mr = Mock() source.factory.master_mr.isRequested = Mock() source.factory.add_unprocessed_txn = Mock() channel = Observable(source) self.tx_manager = P2PTxManagement() self.tx_manager.new_channel(channel) tx = TransferTransaction.create(addrs_to=[get_some_address()], amounts=[1], fee=10, xmss_pk=bytes(67)) event = qrllegacy_pb2.LegacyMessage( func_name=qrllegacy_pb2.LegacyMessage.TX, txData=tx.pbdata) channel.notify(event, force_delivery=True) source.factory.master_mr.isRequested.assert_called() source.factory.add_unprocessed_txn.assert_called()
def test_observable(self): channel = Observable(None) self.tx_manager = P2PTxManagement() self.tx_manager.new_channel(channel) self.assertEquals(8, channel.observers_count)
def test_handle_slave(self, m_Transaction, m_logger): msg = make_message(func_name=qrllegacy_pb2.LegacyMessage.SL, slData=qrl_pb2.Transaction()) P2PTxManagement.handle_slave(self.channel, msg) self.channel.factory.add_unprocessed_txn.assert_called()