class RequestCollector(gevent.Greenlet): def __init__(self, private_key: str, state_db: SharedDatabase, matrix_servers: List[str] = None): super().__init__() self.private_key = private_key self.state_db = state_db state = self.state_db.load_state() self.chain_id = state.blockchain_state.chain_id self.matrix_listener = MatrixListener( private_key=private_key, chain_id=self.chain_id, service_room_suffix=MONITORING_BROADCASTING_ROOM, message_received_callback=self.handle_message, servers=matrix_servers, ) def listen_forever(self) -> None: self.matrix_listener.listen_forever() def _run(self) -> None: # pylint: disable=method-hidden register_error_handler() try: self.matrix_listener.start() self.matrix_listener.startup_finished.wait( timeout=MATRIX_START_TIMEOUT) except (Timeout, ConnectionError) as exc: log.critical("Could not connect to broadcasting system.", exc=exc) sys.exit(1) def stop(self) -> None: self.matrix_listener.stop() self.matrix_listener.join() def handle_message(self, message: Message) -> None: try: if isinstance(message, RequestMonitoring): self.on_monitor_request(message) else: log.debug("Ignoring message", message=message) # add more advanced exception catching except AssertionError as ex: log.error("Error while handling message", message=message, _exc=ex) def on_monitor_request(self, request_monitoring: RequestMonitoring) -> None: assert isinstance(request_monitoring, RequestMonitoring) assert request_monitoring.non_closing_signature is not None assert request_monitoring.reward_proof_signature is not None # Convert Raiden's RequestMonitoring object to a MonitorRequest try: monitor_request = MonitorRequest( channel_identifier=request_monitoring.balance_proof. channel_identifier, token_network_address=TokenNetworkAddress( request_monitoring.balance_proof.token_network_address), chain_id=request_monitoring.balance_proof.chain_id, balance_hash=encode_hex( request_monitoring.balance_proof.balance_hash), nonce=request_monitoring.balance_proof.nonce, additional_hash=encode_hex( request_monitoring.balance_proof.additional_hash), closing_signature=request_monitoring.balance_proof.signature, non_closing_signature=request_monitoring.non_closing_signature, reward_amount=request_monitoring.reward_amount, non_closing_participant=request_monitoring. non_closing_participant, reward_proof_signature=request_monitoring.signature, msc_address=request_monitoring. monitoring_service_contract_address, ) except InvalidSignature: log.info("Ignore MR with invalid signature", monitor_request=request_monitoring) return # Validate MR if monitor_request.chain_id != self.chain_id: log.debug("Bad chain_id", monitor_request=monitor_request, expected=self.chain_id) return if monitor_request.non_closing_signer != monitor_request.non_closing_participant: log.info("MR not signed by non_closing_participant", monitor_request=monitor_request) return if monitor_request.non_closing_signer != monitor_request.reward_proof_signer: log.debug("The two MR signatures don't match", monitor_request=monitor_request) return # Ignore MRs for channels that are already closed for a while. # We need to do this to prevent clients from wasting the MS' gas by # updating the BP after the MS has already called `monitor`, see # https://github.com/raiden-network/raiden-services/issues/504. close_age = self.state_db.channel_close_age( token_network_address=monitor_request.token_network_address, channel_id=monitor_request.channel_identifier, ) # This is x blocks after that event is already confirmed, so that should be plenty! if close_age is not None and close_age >= CHANNEL_CLOSE_MARGIN: log.warning( "Ignore MR for long closed channel", monitor_request=monitor_request, close_age=close_age, ) return # Check that received MR is newer by comparing nonces old_mr = self.state_db.get_monitor_request( token_network_address=monitor_request.token_network_address, channel_id=monitor_request.channel_identifier, non_closing_signer=monitor_request.non_closing_signer, ) if old_mr and old_mr.nonce >= monitor_request.nonce: log.debug( "New MR does not have a newer nonce.", token_network_address=monitor_request.token_network_address, channel_identifier=monitor_request.channel_identifier, received_nonce=monitor_request.nonce, known_nonce=old_mr.nonce, ) return log.info( "Received new MR", token_network_address=monitor_request.token_network_address, channel_identifier=monitor_request.channel_identifier, nonce=monitor_request.nonce, signer=monitor_request.signer, non_closing_signer=monitor_request.non_closing_signer, reward_signer=monitor_request.reward_proof_signer, reward_amount=monitor_request.reward_amount, ) self.state_db.upsert_monitor_request(monitor_request)
class RequestCollector(gevent.Greenlet): def __init__(self, private_key: str, state_db: SharedDatabase): super().__init__() self.private_key = private_key self.state_db = state_db state = self.state_db.load_state() self.chain_id = state.blockchain_state.chain_id self.matrix_listener = MatrixListener( private_key=private_key, chain_id=self.chain_id, service_room_suffix=MONITORING_BROADCASTING_ROOM, message_received_callback=self.handle_message, ) def listen_forever(self) -> None: self.matrix_listener.listen_forever() def _run(self) -> None: # pylint: disable=method-hidden register_error_handler() try: self.matrix_listener.start() except ConnectionError as exc: log.critical("Could not connect to broadcasting system.", exc=exc) sys.exit(1) def stop(self) -> None: self.matrix_listener.stop() self.matrix_listener.join() def handle_message(self, message: Message) -> None: if isinstance(message, RequestMonitoring): self.on_monitor_request(message) else: log.debug("Ignoring message", message=message) def on_monitor_request(self, request_monitoring: RequestMonitoring) -> None: assert isinstance(request_monitoring, RequestMonitoring) assert request_monitoring.non_closing_signature is not None assert request_monitoring.reward_proof_signature is not None # Convert Raiden's RequestMonitoring object to a MonitorRequest try: monitor_request = MonitorRequest( channel_identifier=request_monitoring.balance_proof. channel_identifier, token_network_address=TokenNetworkAddress( request_monitoring.balance_proof.token_network_address), chain_id=request_monitoring.balance_proof.chain_id, balance_hash=encode_hex( request_monitoring.balance_proof.balance_hash), nonce=request_monitoring.balance_proof.nonce, additional_hash=encode_hex( request_monitoring.balance_proof.additional_hash), closing_signature=request_monitoring.balance_proof.signature, non_closing_signature=request_monitoring.non_closing_signature, reward_amount=request_monitoring.reward_amount, # FIXME: not sure why the Signature call is necessary reward_proof_signature=Signature(request_monitoring.signature), ) except InvalidSignature: log.info("Ignore MR with invalid signature", monitor_request=request_monitoring) return # Validate MR if monitor_request.chain_id != self.chain_id: log.debug("Bad chain_id", monitor_request=monitor_request, expected=self.chain_id) return # Check that received MR is newer by comparing nonces old_mr = self.state_db.get_monitor_request( token_network_address=monitor_request.token_network_address, channel_id=monitor_request.channel_identifier, non_closing_signer=monitor_request.non_closing_signer, ) if old_mr and old_mr.nonce >= monitor_request.nonce: log.debug( "New MR does not have a newer nonce.", token_network_address=monitor_request.token_network_address, channel_identifier=monitor_request.channel_identifier, received_nonce=monitor_request.nonce, known_nonce=old_mr.nonce, ) return log.info( "Received new MR", token_network_address=monitor_request.token_network_address, channel_identifier=monitor_request.channel_identifier, nonce=monitor_request.nonce, signer=monitor_request.signer, non_closing_signer=monitor_request.non_closing_signer, reward_signer=monitor_request.reward_proof_signer, reward_amount=monitor_request.reward_amount, ) with self.state_db.conn: self.state_db.upsert_monitor_request(monitor_request)
class RequestCollector(gevent.Greenlet): def __init__( self, private_key: str, state_db: SharedDatabase, ): super().__init__() self.private_key = private_key self.state_db = state_db state = self.state_db.load_state() try: self.matrix_listener = MatrixListener( private_key=private_key, chain_id=state.blockchain_state.chain_id, callback=self.handle_message, service_room_suffix=MONITORING_BROADCASTING_ROOM, ) except ConnectionError as e: log.critical( 'Could not connect to broadcasting system.', exc=e, ) sys.exit(1) def listen_forever(self): self.matrix_listener.listen_forever() def _run(self): register_error_handler(error_handler) self.matrix_listener.start() def stop(self): self.matrix_listener.stop() self.matrix_listener.join() def handle_message(self, message: SignedMessage): if isinstance(message, RequestMonitoring): self.on_monitor_request(message) else: log.info('Ignoring unknown message type') def on_monitor_request( self, request_monitoring: RequestMonitoring, ): assert isinstance(request_monitoring, RequestMonitoring) # Convert Raiden's RequestMonitoring object to a MonitorRequest try: monitor_request = MonitorRequest( channel_identifier=request_monitoring.balance_proof. channel_identifier, token_network_address=to_checksum_address( request_monitoring.balance_proof.token_network_address, ), chain_id=request_monitoring.balance_proof.chain_id, balance_hash=encode_hex( request_monitoring.balance_proof.balance_hash), nonce=request_monitoring.balance_proof.nonce, additional_hash=encode_hex( request_monitoring.balance_proof.additional_hash), closing_signature=encode_hex( request_monitoring.balance_proof.signature), non_closing_signature=encode_hex( request_monitoring.non_closing_signature), reward_amount=request_monitoring.reward_amount, reward_proof_signature=encode_hex( request_monitoring.signature), ) except InvalidSignature: log.info( 'Ignore MR with invalid signature', monitor_request=request_monitoring, ) return # Check that received MR is newer by comparing nonces old_mr = self.state_db.get_monitor_request( token_network_address=monitor_request.token_network_address, channel_id=monitor_request.channel_identifier, non_closing_signer=monitor_request.non_closing_signer, ) if old_mr and old_mr.nonce >= monitor_request.nonce: log.debug( 'New MR does not have a newer nonce.', token_network_address=monitor_request.token_network_address, channel_identifier=monitor_request.channel_identifier, received_nonce=monitor_request.nonce, known_nonce=old_mr.nonce, ) return log.info( 'Received new MR', token_network_address=monitor_request.token_network_address, channel_identifier=monitor_request.channel_identifier, nonce=monitor_request.nonce, signer=monitor_request.signer, non_closing_signer=monitor_request.non_closing_signer, reward_signer=monitor_request.reward_proof_signer, reward_amount=monitor_request.reward_amount, ) with self.state_db.conn: self.state_db.upsert_monitor_request(monitor_request)