def handle(self, connection_id, message_content): set_request = state_context_pb2.TpStateSetRequest() set_request.ParseFromString(message_content) set_values_list = [{e.address: e.data} for e in set_request.entries] try: return_value = self._context_manager.set(set_request.context_id, set_values_list) except AuthorizationException: response = \ state_context_pb2.TpStateSetResponse( status=state_context_pb2. TpStateSetResponse.AUTHORIZATION_ERROR) return HandlerResult(HandlerStatus.RETURN, response, validator_pb2.Message.TP_STATE_SET_RESPONSE) response = state_context_pb2.TpStateSetResponse( status=state_context_pb2.TpStateSetResponse.OK) if return_value is True: address_list = [e.address for e in set_request.entries] response.addresses.extend(address_list) else: LOGGER.debug("SET: No Values Set") response.addresses.extend([]) return HandlerResult(HandlerStatus.RETURN, response, validator_pb2.Message.TP_STATE_SET_RESPONSE)
def handle(self, connection_id, message_content): if not self._can_accept(): if not self._applying_backpressure: self._applying_backpressure = True LOGGER.info( 'Applying back pressure on client submitted batches: ' 'current depth: %s, limit: %s', *self._queue_info()) self._batches_rejected_count.inc() self._batches_rejected_gauge.set_value( self._batches_rejected_gauge.get_value() + 1) response = ClientBatchSubmitResponse( status=ClientBatchSubmitResponse.QUEUE_FULL) return HandlerResult( status=HandlerStatus.RETURN, message_out=response, message_type=Message.CLIENT_BATCH_SUBMIT_RESPONSE) else: if self._applying_backpressure: self._applying_backpressure = False self._batches_rejected_gauge.set_value(0) LOGGER.info( 'Ending back pressure on client submitted batches: ' 'current depth: %s, limit: %s', *self._queue_info()) return HandlerResult(status=HandlerStatus.PASS)
def handle(self, connection_id, message_content): gossip_message = GossipMessage() gossip_message.ParseFromString(message_content) if gossip_message.content_type == gossip_message.BLOCK: block = Block() block.ParseFromString(gossip_message.content) has_block = False if self._completer.get_block(block.header_signature) is not None: has_block = True if not has_block and self._has_block(block.header_signature): has_block = True if has_block: return HandlerResult(HandlerStatus.DROP) if gossip_message.content_type == gossip_message.BATCH: batch = Batch() batch.ParseFromString(gossip_message.content) has_batch = False if self._completer.get_batch(batch.header_signature) is not None: has_batch = True if not has_batch and self._has_batch(batch.header_signature): has_batch = True if has_batch: return HandlerResult(HandlerStatus.DROP) return HandlerResult(HandlerStatus.PASS)
def handle(self, connection_id, message_content): get_request = state_context_pb2.TpStateGetRequest() get_request.ParseFromString(message_content) try: return_values = self._context_manager.get( get_request.context_id, list(get_request.addresses)) except AuthorizationException: response = \ state_context_pb2.TpStateGetResponse( status=state_context_pb2. TpStateGetResponse.AUTHORIZATION_ERROR) return HandlerResult(HandlerStatus.RETURN, response, validator_pb2.Message.TP_STATE_GET_RESPONSE) return_list = return_values if return_values is not None else [] entry_list = [ state_context_pb2.TpStateEntry(address=a, data=d) for a, d in return_list ] response = state_context_pb2.TpStateGetResponse( status=state_context_pb2.TpStateGetResponse.OK) response.entries.extend(entry_list) return HandlerResult(HandlerStatus.RETURN, response, validator_pb2.Message.TP_STATE_GET_RESPONSE)
def handle(self, connection_id, message_content): block_response = network_pb2.GossipBlockResponse() block_response.ParseFromString(message_content) block = block_pb2.Block() block.ParseFromString(block_response.content) open_request = self._responder.get_request(block.header_signature) if open_request is None: return HandlerResult(status=HandlerStatus.PASS) for connection in open_request: LOGGER.debug("Responding to block request: Send %s to %s", block.header_signature, connection) try: self._gossip.send(validator_pb2.Message.GOSSIP_BLOCK_RESPONSE, message_content, connection) except ValueError: LOGGER.debug("Can't send block response %s to closed " "connection %s", block.header_signature, connection) self._responder.remove_request(block.header_signature) return HandlerResult(HandlerStatus.PASS)
def handle(self, connection_id, message_content): # check to see if there is a public key public_key = self._network.connection_id_to_public_key(connection_id) if public_key is None: LOGGER.debug( "No public key found, %s is not permitted. " "Close connection.", connection_id) violation = AuthorizationViolation( violation=RoleType.Value("NETWORK")) self._gossip.unregister_peer(connection_id) return HandlerResult( HandlerStatus.RETURN_AND_CLOSE, message_out=violation, message_type=validator_pb2.Message.AUTHORIZATION_VIOLATION) # check public key against network/default role permitted = self._permission_verifier.check_network_role(public_key) if not permitted: LOGGER.debug("Public key not permitted, %s is not permitted", connection_id) self._gossip.unregister_peer(connection_id) violation = AuthorizationViolation( violation=RoleType.Value("NETWORK")) return HandlerResult( HandlerStatus.RETURN_AND_CLOSE, message_out=violation, message_type=validator_pb2.Message.AUTHORIZATION_VIOLATION) # if allowed pass message return HandlerResult(HandlerStatus.PASS)
def handle(self, connection_id, message_content): message = GossipMessage() message.ParseFromString(message_content) if message.content_type == GossipMessage.BLOCK: public_key = \ self._network.connection_id_to_public_key(connection_id) block = Block() block.ParseFromString(message.content) header = BlockHeader() header.ParseFromString(block.header) if header.signer_public_key == public_key: permitted = \ self._permission_verifier.check_network_consensus_role( public_key) if not permitted: LOGGER.debug( "Public key is not permitted to publish block, " "remove connection: %s", connection_id) self._gossip.unregister_peer(connection_id) violation = AuthorizationViolation( violation=RoleType.Value("NETWORK")) return HandlerResult(HandlerStatus.RETURN_AND_CLOSE, message_out=violation, message_type=validator_pb2.Message. AUTHORIZATION_VIOLATION) # if allowed pass message return HandlerResult(HandlerStatus.PASS)
def handle(self, connection_id, message_content): exclude = [connection_id] gossip_message = GossipMessage() gossip_message.ParseFromString(message_content) if gossip_message.time_to_live == 0: # Do not forward message if it has reached its time to live limit return HandlerResult(status=HandlerStatus.PASS) else: # decrement time_to_live time_to_live = gossip_message.time_to_live gossip_message.time_to_live = time_to_live - 1 if gossip_message.content_type == GossipMessage.BATCH: batch = Batch() batch.ParseFromString(gossip_message.content) # If we already have this batch, don't forward it if not self._completer.get_batch(batch.header_signature): self._gossip.broadcast_batch(batch, exclude) elif gossip_message.content_type == GossipMessage.BLOCK: block = Block() block.ParseFromString(gossip_message.content) # If we already have this block, don't forward it if not self._completer.get_block(block.header_signature): self._gossip.broadcast_block(block, exclude) else: LOGGER.info("received %s, not BATCH or BLOCK", gossip_message.content_type) return HandlerResult(status=HandlerStatus.PASS)
def handle(self, connection_id, message_content): batch_response_message = GossipBatchResponse() batch_response_message.ParseFromString(message_content) batch = Batch() batch.ParseFromString(batch_response_message.content) if not is_valid_batch(batch): LOGGER.debug("requested batch's structure is invalid: %s", batch.header_signature) return HandlerResult(status=HandlerStatus.DROP) return HandlerResult(status=HandlerStatus.PASS)
def handle(self, connection_id, message_content): block_response_message = GossipBlockResponse() block_response_message.ParseFromString(message_content) block = Block() block.ParseFromString(block_response_message.content) if not is_valid_block(block): LOGGER.debug("requested block's batches structure is invalid: %s", block.header_signature) return HandlerResult(status=HandlerStatus.DROP) return HandlerResult(status=HandlerStatus.PASS)
def handle(self, connection_id, message_content): block_request_message = network_pb2.GossipBlockRequest() block_request_message.ParseFromString(message_content) if block_request_message.nonce in self._seen_requests: LOGGER.debug("Received repeat GossipBlockRequest from %s", connection_id) return HandlerResult(HandlerStatus.DROP) block_id = block_request_message.block_id block = self._responder.check_for_block(block_id) if block is None: # No block found, broadcast original message to other peers # and add to pending requests if block_id == "HEAD": LOGGER.debug("No chain head available. Cannot respond to block" " requests.") else: if not self._responder.already_requested(block_id): if block_request_message.time_to_live > 0: time_to_live = block_request_message.time_to_live block_request_message.time_to_live = time_to_live - 1 self._gossip.broadcast( block_request_message, validator_pb2.Message.GOSSIP_BLOCK_REQUEST, exclude=[connection_id]) self._seen_requests[block_request_message.nonce] = \ block_request_message.block_id self._responder.add_request(block_id, connection_id) else: LOGGER.debug("Block %s has already been requested", block_id) self._responder.add_request(block_id, connection_id) else: LOGGER.debug("Responding to block requests: %s", block.get_block().header_signature) block_response = network_pb2.GossipBlockResponse( content=block.get_block().SerializeToString()) self._gossip.send(validator_pb2.Message.GOSSIP_BLOCK_RESPONSE, block_response.SerializeToString(), connection_id) return HandlerResult(HandlerStatus.PASS)
def handle(self, connection_id, message_content): batch_request_message = network_pb2.GossipBatchByBatchIdRequest() batch_request_message.ParseFromString(message_content) if batch_request_message.nonce in self._seen_requests: LOGGER.debug("Received repeat GossipBatchByBatchIdRequest from %s", connection_id) return HandlerResult(HandlerStatus.DROP) batch = None batch = self._responder.check_for_batch(batch_request_message.id) if batch is None: # No batch found, broadcast original message to other peers # and add to pending requests if not self._responder.already_requested(batch_request_message.id): if batch_request_message.time_to_live > 0: time_to_live = batch_request_message.time_to_live batch_request_message.time_to_live = time_to_live - 1 self._gossip.broadcast( batch_request_message, validator_pb2.Message.GOSSIP_BATCH_BY_BATCH_ID_REQUEST, exclude=[connection_id]) self._seen_requests[batch_request_message.nonce] = \ batch_request_message.id self._responder.add_request(batch_request_message.id, connection_id) else: LOGGER.debug("Batch %s has already been requested", batch_request_message.id) self._responder.add_request(batch_request_message.id, connection_id) else: LOGGER.debug("Responding to batch requests %s", batch.header_signature) batch_response = network_pb2.GossipBatchResponse( content=batch.SerializeToString(), ) self._gossip.send(validator_pb2.Message.GOSSIP_BATCH_RESPONSE, batch_response.SerializeToString(), connection_id) return HandlerResult(HandlerStatus.PASS)
def handle(self, connection_id, message_content): block_response_message = GossipBlockResponse() block_response_message.ParseFromString(message_content) block = Block() block.ParseFromString(block_response_message.content) if block.header_signature in self._seen_cache: self.block_dropped_count.inc() return HandlerResult(status=HandlerStatus.DROP) if not is_valid_block(block): LOGGER.debug("requested block's signature is invalid: %s", block.header_signature) return HandlerResult(status=HandlerStatus.DROP) self._seen_cache = TimedCache() return HandlerResult(status=HandlerStatus.PASS)
def handle(self, connection_id, message_content): batch_response = network_pb2.GossipBatchResponse() batch_response.ParseFromString(message_content) batch = batch_pb2.Batch() batch.ParseFromString(batch_response.content) open_request = self._responder.get_request(batch.header_signature) if open_request is None: open_request = [] requests_to_remove = [batch.header_signature] for txn in batch.transactions: requests_by_txn = self._responder.get_request(txn.header_signature) if requests_by_txn is not None: open_request += requests_by_txn requests_to_remove += [txn.header_signature] for connection in open_request: LOGGER.debug("Responding to batch requests: Send %s to %s", batch.header_signature, connection) try: self._gossip.send(validator_pb2.Message.GOSSIP_BATCH_RESPONSE, message_content, connection) except ValueError: LOGGER.debug("Can't send batch response %s to closed " "connection %s", batch.header_signature, connection) for requested_id in requests_to_remove: self._responder.remove_request(requested_id) return HandlerResult(HandlerStatus.PASS)
def handle(self, connection_id, message_content): request = processor_pb2.TpRegisterRequest() request.ParseFromString(message_content) if request.max_occupancy == 0: max_occupancy = DEFAULT_MAX_OCCUPANCY LOGGER.warning( 'Max occupancy was not provided by transaction processor: %s.' ' Using default max occupancy: %s', connection_id, DEFAULT_MAX_OCCUPANCY) else: max_occupancy = request.max_occupancy LOGGER.info( 'registered transaction processor: connection_id=%s, family=%s, ' 'version=%s, namespaces=%s, max_occupancy=%s', connection_id, request.family, request.version, list(request.namespaces), max_occupancy) processor_type = processor_manager.ProcessorType( request.family, request.version) processor = processor_manager.Processor(connection_id, request.namespaces, max_occupancy) self._collection[processor_type] = processor ack = processor_pb2.TpRegisterResponse() ack.status = ack.OK return HandlerResult( status=HandlerStatus.RETURN, message_out=ack, message_type=validator_pb2.Message.TP_REGISTER_RESPONSE)
def _network_violation_result(): violation = AuthorizationViolation( violation=RoleType.Value("NETWORK")) return HandlerResult( HandlerStatus.RETURN_AND_CLOSE, message_out=violation, message_type=validator_pb2.Message.AUTHORIZATION_VIOLATION)
def handle(self, connection_id, message_content): response_proto = client_batch_submit_pb2.ClientBatchSubmitResponse def make_response(out_status): return HandlerResult( status=HandlerStatus.RETURN, message_out=response_proto(status=out_status), message_type=Message.CLIENT_BATCH_SUBMIT_RESPONSE) try: request = client_batch_submit_pb2.ClientBatchSubmitRequest() request.ParseFromString(message_content) for batch in request.batches: if batch.trace: LOGGER.debug("TRACE %s: %s", batch.header_signature, self.__class__.__name__) if not all( self._verifier.check_off_chain_batch_roles(batch) for batch in request.batches): return make_response(response_proto.INVALID_BATCH) if not all( self._verifier.is_batch_signer_authorized(batch) for batch in request.batches): return make_response(response_proto.INVALID_BATCH) except DecodeError: return make_response(response_proto.INTERNAL_ERROR) return HandlerResult(status=HandlerStatus.PASS)
def handle(self, connection_id, message_content): request = ClientEventsSubscribeRequest() request.ParseFromString(message_content) ack = ClientEventsSubscribeResponse() try: subscriptions = [ EventSubscription( event_type=sub.event_type, filters=[ self._filter_factory.create(f.key, f.match_string, f.filter_type) for f in sub.filters ], ) for sub in request.subscriptions ] except InvalidFilterError as err: LOGGER.warning("Invalid Filter Error: %s", err) ack.status = ack.INVALID_FILTER ack.response_message = str(err) return HandlerResult(HandlerStatus.RETURN, message_out=ack, message_type=self._msg_type) last_known_block_ids = list(request.last_known_block_ids) last_known_block_id = None if last_known_block_ids: try: last_known_block_id = \ self._event_broadcaster.get_latest_known_block_id( last_known_block_ids) except NoKnownBlockError as err: ack.status = ack.UNKNOWN_BLOCK ack.response_message = str(err) return HandlerResult(HandlerStatus.RETURN, message_out=ack, message_type=self._msg_type) self._event_broadcaster.add_subscriber(connection_id, subscriptions, last_known_block_id) ack.status = ack.OK return HandlerResult(HandlerStatus.RETURN_AND_PASS, message_out=ack, message_type=self._msg_type)
def handle(self, connection_id, message_content): batch_response_message = GossipBatchResponse() batch_response_message.ParseFromString(message_content) batch = Batch() batch.ParseFromString(batch_response_message.content) if batch.header_signature in self._seen_cache: self._batch_dropped_count.inc() return HandlerResult(status=HandlerStatus.DROP) if not is_valid_batch(batch): LOGGER.debug("requested batch's signature is invalid: %s", batch.header_signature) return HandlerResult(status=HandlerStatus.DROP) self._seen_cache[batch.header_signature] = None return HandlerResult(status=HandlerStatus.PASS)
def handle(self, connection_id, message_content): # Attempt to catch the subscriber up with events try: self._event_broadcaster.catchup_subscriber(connection_id) except (PossibleForkDetectedError, NoKnownBlockError, KeyError) as err: LOGGER.warning("Failed to catchup subscriber: %s", err) self._event_broadcaster.enable_subscriber(connection_id) return HandlerResult(HandlerStatus.PASS)
def handle(self, connection_id, message_content): block_response_message = network_pb2.GossipBlockResponse() block_response_message.ParseFromString(message_content) block = Block() block.ParseFromString(block_response_message.content) self._completer.add_block(block) return HandlerResult(status=HandlerStatus.PASS)
def handle(self, connection_id, message_content): batch_response_message = network_pb2.GossipBatchResponse() batch_response_message.ParseFromString(message_content) batch = Batch() batch.ParseFromString(batch_response_message.content) self._completer.add_batch(batch) return HandlerResult(status=HandlerStatus.PASS)
def handle(self, connection_id, message_content): request = ClientBatchSubmitRequest() request.ParseFromString(message_content) for batch in request.batches: if batch.trace: LOGGER.debug("TRACE %s: %s", batch.header_signature, self.__class__.__name__) self._completer.add_batch(batch) self._gossip.broadcast_batch(batch) return HandlerResult(status=HandlerStatus.PASS)
def handle(self, connection_id, message_content): delete_request = state_context_pb2.TpStateDeleteRequest() delete_request.ParseFromString(message_content) try: self._context_manager.delete(delete_request.context_id, list(delete_request.addresses)) except AuthorizationException: response = \ state_context_pb2.TpStateDeleteResponse( status=state_context_pb2. TpStateDeleteResponse.AUTHORIZATION_ERROR) return HandlerResult( HandlerStatus.RETURN, response, validator_pb2.Message.TP_STATE_DELETE_RESPONSE) response = state_context_pb2.TpStateDeleteResponse( addresses=delete_request.addresses, status=state_context_pb2.TpStateDeleteResponse.OK) return HandlerResult(HandlerStatus.RETURN, response, validator_pb2.Message.TP_STATE_DELETE_RESPONSE)
def handle(self, connection_id, message_content): gossip_message = network_pb2.GossipMessage() gossip_message.ParseFromString(message_content) if gossip_message.content_type == network_pb2.GossipMessage.BLOCK: block = Block() block.ParseFromString(gossip_message.content) self._completer.add_block(block) elif gossip_message.content_type == network_pb2.GossipMessage.BATCH: batch = Batch() batch.ParseFromString(gossip_message.content) self._completer.add_batch(batch) return HandlerResult(status=HandlerStatus.PASS)
def handle(self, connection_id, message_content): response = GetPeersResponse() response.ParseFromString(message_content) LOGGER.debug( "Got peers response message from %s. Endpoints: %s", connection_id, response.peer_endpoints) self._gossip.add_candidate_peer_endpoints(response.peer_endpoints) return HandlerResult(HandlerStatus.PASS)
def handle(self, connection_id, message_content): """ If an AuthorizationViolation is recieved, the connection has decided that this validator is no longer permitted to be connected. Remove the connection preemptively. """ LOGGER.warning("Received AuthorizationViolation from %s", connection_id) # Close the connection endpoint = self._network.connection_id_to_endpoint(connection_id) self._network.remove_connection(connection_id) self._gossip.remove_temp_endpoint(endpoint) return HandlerResult(HandlerStatus.DROP)
def handle(self, connection_id, message_content): request = ClientEventsGetRequest() request.ParseFromString(message_content) resp = ClientEventsGetResponse() try: subscriptions = [ EventSubscription( event_type=sub.event_type, filters=[ self._filter_factory.create(f.key, f.match_string, f.filter_type) for f in sub.filters ], ) for sub in request.subscriptions ] except InvalidFilterError as err: LOGGER.warning("Invalid Filter Error: %s", err) resp.status = resp.INVALID_FILTER return HandlerResult( HandlerStatus.RETURN, message_out=resp, message_type=validator_pb2.Message.CLIENT_EVENTS_GET_RESPONSE) try: events = self._event_broadcaster.get_events_for_block_ids( request.block_ids, subscriptions) except KeyError: resp.status = resp.UNKNOWN_BLOCK return HandlerResult( HandlerStatus.RETURN, message_out=resp, message_type=validator_pb2.Message.CLIENT_EVENTS_GET_RESPONSE) resp.events.extend(events) resp.status = resp.OK return HandlerResult( HandlerStatus.RETURN, message_out=resp, message_type=validator_pb2.Message.CLIENT_EVENTS_GET_RESPONSE)
def _wrap_result(self, response): """Wraps child's response in a HandlerResult to be sent back to client. Args: response (enum or dict): Either an integer status enum, or a dict of attributes to be added to the protobuf response. """ if isinstance(response, int): response = self._wrap_response(response) return HandlerResult(status=HandlerStatus.RETURN, message_out=self._response_proto(**response), message_type=self._response_type)
def handle(self, connection_id, message_content): batch_response_message = GossipBatchResponse() batch_response_message.ParseFromString(message_content) batch = Batch() batch.ParseFromString(batch_response_message.content) batch_id = batch.header_signature ack = NetworkAcknowledgement() ack.status = ack.OK if not self._has_open_requests(batch_id) and self._has_batch(batch_id): return HandlerResult( HandlerStatus.RETURN, message_out=ack, message_type=validator_pb2.Message.NETWORK_ACK ) return HandlerResult( HandlerStatus.RETURN_AND_PASS, message_out=ack, message_type=validator_pb2.Message.NETWORK_ACK)