示例#1
0
    def __handler_status(self, request, context):
        util.logger.debug(f"peer_outer_service:handler_status ({request.message})")

        if request.message == "get_stub_manager_to_server":
            # this case is check only gRPC available
            return loopchain_pb2.Message(code=message_code.Response.success)

        channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel
        channel_stub = StubCollection().channel_stubs[channel_name]

        if request.message == "check peer status by rs":
            channel_stub.sync_task().reset_timer(TimerService.TIMER_KEY_CONNECT_PEER)

        callback = partial(self.__status_update, request.channel)
        future = asyncio.run_coroutine_threadsafe(
            channel_stub.async_task().get_status(),
            self.peer_service.inner_service.loop
        )
        future.add_done_callback(callback)

        status = self.__get_status_peer_type_data(request.channel)
        if status is None:
            return loopchain_pb2.Message(code=message_code.Response.fail)

        meta = json.loads(request.meta) if request.meta else {}
        if meta.get("highest_block_height", None) and meta["highest_block_height"] > status["block_height"]:
            util.logger.spam(f"(peer_outer_service.py:__handler_status) there is difference of height !")
            channel_stub.sync_task().block_height_sync()

        status_json = json.dumps(status)

        return loopchain_pb2.Message(code=message_code.Response.success, meta=status_json)
示例#2
0
    def __handler_get_configuration(self, request, context):
        """Get Configuration

        :param request: proto.Message {meta=configuration_name}
        :param context:
        :return: proto.Message {meta=configuration_info(s)}
        """

        if request.meta == '':
            result = conf.get_all_configurations()
        else:
            meta = json.loads(request.meta)
            conf_name = meta['name']
            result = conf.get_configuration(conf_name)

        if result is None:
            return loopchain_pb2.Message(
                code=message_code.Response.fail,
                message="'" + conf_name + "' is an incorrect configuration name."
            )
        else:
            json_result = json.dumps(result)
            return loopchain_pb2.Message(
                code=message_code.Response.success,
                meta=json_result
            )
示例#3
0
    def __handler_complain_leader(self, request, context):
        """Complain Leader Peer

        :param request: proto.Message {message=group_id}
        :param context:
        :return: proto.Message {object=leader_peer_object}
        """

        # 현재 leader peer status 확인 후 맞으면 peer id 를
        # 아니면 complain 한 peer 로 leader 를 변경 후 응답한다.

        # 선택된 peer 가 leader 로 동작하고 있는지 확인 후 지정하는데 만약
        # get_leader_peer 한 내용과 다르면 AnnounceNewLeader 를 broadcast 하여야 한다.

        logging.debug("in complain leader (radiostation)")
        leader_peer = ObjectManager(
        ).rs_service.channel_manager.get_peer_manager(
            conf.LOOPCHAIN_DEFAULT_CHANNEL).complain_leader(
                group_id=request.message)
        if leader_peer is not None:
            logging.warning(
                f"leader_peer after complain({leader_peer.peer_id})")
            peer_dump = pickle.dumps(leader_peer)
            return loopchain_pb2.Message(code=message_code.Response.success,
                                         object=peer_dump)

        return loopchain_pb2.Message(
            code=message_code.Response.fail_no_leader_peer)
示例#4
0
    def Request(self, request, context):
        logging.debug("RadioStationService got request: " + str(request))

        if request.code in self.__handler_map.keys():
            return self.__handler_map[request.code](request, context)

        return loopchain_pb2.Message(code=message_code.Response.not_treat_message_code)
示例#5
0
 def __handler_peer_list(self, request, context):
     message = "All Group Peers count: " + str(
         len(self.peer_service.peer_list.peer_list[conf.ALL_GROUP_ID]))
     return loopchain_pb2.Message(
         code=message_code.Response.success,
         message=message,
         meta=str(self.peer_service.peer_list.peer_list))
示例#6
0
    def __handler_get_balance(self, request, context):
        """Get Balance Tx for json-rpc request

        :param request:
        :param context:
        :return:
        """
        params = json.loads(request.meta)
        if 'address' not in params.keys():
            return loopchain_pb2.Message(code=message_code.Response.fail_illegal_params)

        query_request = loopchain_pb2.QueryRequest(params=request.meta, channel=request.channel)
        response = self.Query(query_request, context)
        util.logger.spam(f"peer_outer_service:__handler_get_balance response({response})")

        return loopchain_pb2.Message(code=response.response_code, meta=response.response)
示例#7
0
    def Request(self, request, context):
        # util.logger.debug(f"Peer Service got request({request.code})")

        if request.code in self.__handler_map.keys():
            return self.__handler_map[request.code](request, context)

        return loopchain_pb2.Message(code=message_code.Response.not_treat_message_code)
示例#8
0
    def GetScoreStatus(self, request, context):
        """Score Service 의 현재 상태를 요청 한다

        :param request:
        :param context:
        :return:
        """
        logging.debug("Peer GetScoreStatus request : %s", request)
        score_status = json.loads("{}")
        channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel
        try:
            score_status_response = self.peer_service.channel_manager.get_score_container_stub(
                channel_name).call(
                    "Request",
                    loopchain_pb2.Message(code=message_code.Request.status))
            logging.debug("Get Score Status : " + str(score_status_response))
            if score_status_response.code == message_code.Response.success:
                score_status = json.loads(score_status_response.meta)

        except Exception as e:
            logging.debug("Score Service Already stop by other reason. %s", e)

        return loopchain_pb2.StatusReply(status=json.dumps(score_status),
                                         block_height=0,
                                         total_tx=0)
    def Request(self, request, context):
        logging.debug(f"rs_outer_service:Request({request})")

        if request.code in self.__handler_map.keys():
            return self.__handler_map[request.code](request, context)

        return loopchain_pb2.Message(code=message_code.Response.not_treat_message_code)
示例#10
0
    def __handler_reconnect_to_rs(self, request, context):
        logging.warning(f"RS lost peer info (candidate reason: RS restart)")
        logging.warning(f"try reconnect to RS....")
        ObjectManager().peer_service.connect_to_radiostation(
            channel=request.channel, is_reconnect=True)

        return loopchain_pb2.Message(code=message_code.Response.success)
示例#11
0
    def __handler_get_leader_peer(self, request, context):
        """Get Leader Peer

        :param request: proto.Message {message=group_id}
        :param context:
        :return: proto.Message {object=leader_peer_object}
        """

        # TODO 현재는 peer_list.get_leader_peer 가 서브 그룹 리더에 대한 처리를 제공하지 않고 있다.
        leader_peer = self.__peer_manager.get_leader_peer(group_id=request.message, is_peer=False)
        if leader_peer is not None:
            logging.debug(f"leader_peer ({leader_peer.peer_id})")
            peer_dump = pickle.dumps(leader_peer)

            return loopchain_pb2.Message(code=message_code.Response.success, object=peer_dump)

        return loopchain_pb2.Message(code=message_code.Response.fail_no_leader_peer)
示例#12
0
    def __handler_set_configuration(self, request, context):
        """Set Configuration

        :param request: proto.Message {meta=configuration_info}
        :param context:
        :return: proto.Message
        """

        meta = json.loads(request.meta)

        if conf.set_configuration(meta['name'], meta['value']):
            return loopchain_pb2.Message(code=message_code.Response.success)
        else:
            return loopchain_pb2.Message(
                code=message_code.Response.fail,
                message='"' + meta['name'] +
                '" does not exist in the loopchain configuration list.')
示例#13
0
    def __handler_get_leader_peer(self, request, context):
        """Get Leader Peer

        :param request: proto.Message {message=group_id}
        :param context:
        :return: proto.Message {object=leader_peer_object}
        """
        channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if not request.channel else request.channel
        leader_peer: PeerInfo = ObjectManager().rs_service.channel_manager.get_peer_manager(
            channel_name).get_leader_peer(group_id=request.message, is_peer=False)
        if leader_peer is not None:
            logging.debug(f"leader_peer ({leader_peer.peer_id})")
            peer_dumped = leader_peer.dump()

            return loopchain_pb2.Message(code=message_code.Response.success, object=peer_dumped)

        return loopchain_pb2.Message(code=message_code.Response.fail_no_leader_peer)
示例#14
0
    def announce_new_leader(self, complained_leader_id, new_leader_id, is_broadcast=True, self_peer_id=None):
        """Announce New Leader Id to Network

        :param complained_leader_id:
        :param new_leader_id:
        :param is_broadcast: False(notify to RS only), True(broadcast to network include RS)
        :param self_peer_id:
        :return:
        """
        util.logger.spam(f"peer_manager:announce_new_leader channel({self.__channel_name}), "
                         f"complained_leader_id({complained_leader_id}), "
                         f"new_leader_id({new_leader_id}), "
                         f"is_broadcast({is_broadcast})")
        is_rs = ObjectManager().rs_service is not None

        announce_message = loopchain_pb2.ComplainLeaderRequest(
            complained_leader_id=complained_leader_id,
            channel=self.__channel_name,
            new_leader_id=new_leader_id,
            message="Announce New Leader"
        )

        # new_leader_peer = self.get_peer(new_leader_id)

        # Announce New Leader to Radio station
        try:
            channel_service = ObjectManager().channel_service
            if channel_service:
                response = channel_service.radio_station_stub.call("AnnounceNewLeader", announce_message)
                if response.response_code == message_code.Response.fail_no_peer_info_in_rs:
                    util.logger.spam(
                        f"peer_manager:announce_new_leader fail no peer info in rs! is_broadcast({is_broadcast})")
                    announce_message.message = message_code.get_response_msg(
                        message_code.Response.fail_no_peer_info_in_rs)
                    ObjectManager().channel_service.connect_to_radio_station(is_reconnect=True)

                    ObjectManager().channel_service.broadcast_scheduler.schedule_broadcast(
                        "Request",
                        loopchain_pb2.Message(
                            code=message_code.Request.peer_reconnect_to_rs,
                            channel=self.__channel_name))
        except Exception as e:
            # logging.debug("in RS there is no peer_service....")
            is_rs = True

        if is_broadcast is True:
            for peer_id in list(self.peer_list[conf.ALL_GROUP_ID]):
                if new_leader_id == peer_id and is_rs is not True:
                    util.logger.spam(f"Prevent reset leader loop in AnnounceNewLeader message")
                    continue

                peer_each = self.peer_list[conf.ALL_GROUP_ID][peer_id]
                stub_manager = self.get_peer_stub_manager(peer_each, conf.ALL_GROUP_ID)
                try:
                    stub_manager.call_async("AnnounceNewLeader", announce_message, is_stub_reuse=True)
                except Exception as e:
                    logging.warning("gRPC Exception: " + str(e))
                    logging.debug("No response target: " + str(peer_each.target))
示例#15
0
    def __handler_restart_channel(self, request, context):
        logging.debug(f"Restart_channel({request.channel}) code({request.code}), message({request.message})")

        ObjectManager().peer_service.start_channel(
            channel=request.channel,
            is_restart=True
        )

        return loopchain_pb2.Message(code=message_code.Response.success)
示例#16
0
    def check_peer_status(self, group_id=None):
        if group_id is None:
            group_id = conf.ALL_GROUP_ID
        nonresponse_peer_list = []
        check_leader_peer_count = 0

        for peer_id in list(self.__peer_object_list[group_id]):
            peer_info: PeerInfo = self.peer_list[group_id][peer_id]
            stub_manager = self.get_peer_stub_manager(peer_info, group_id)
            peer_object: PeerObject = self.__peer_object_list[group_id][peer_id]

            try:
                response = stub_manager.call(
                    "Request", loopchain_pb2.Message(
                        code=message_code.Request.status,
                        channel=self.__channel_name,
                        message="check peer status by rs",
                        meta=json.dumps({"highest_block_height": self.__highest_block_height})
                    ), is_stub_reuse=True)
                if response.code != message_code.Response.success:
                    raise Exception

                peer_object.no_response_count_reset()
                peer_info.status = PeerStatus.connected
                peer_status = json.loads(response.meta)

                if peer_status["state"] == "BlockGenerate":
                    check_leader_peer_count += 1

                if peer_status["block_height"] >= self.__highest_block_height:
                    self.__highest_block_height = peer_status["block_height"]
            except Exception as e:
                util.apm_event(conf.RADIO_STATION_NAME, {
                    'event_type': 'DisconnectedPeer',
                    'peer_name': conf.PEER_NAME,
                    'channel_name': self.__channel_name,
                    'data': {
                        'message': 'there is disconnected peer gRPC Exception: ' + str(e),
                        'peer_id': peer_info.peer_id}})

                logging.warning("there is disconnected peer peer_id(" + peer_info.peer_id +
                                ") gRPC Exception: " + str(e))
                peer_object.no_response_count_up()

                util.logger.spam(
                    f"peer_manager::check_peer_status "
                    f"peer_id({peer_object.peer_info.peer_id}) "
                    f"no response count up({peer_object.no_response_count})")

                if peer_object.no_response_count >= conf.NO_RESPONSE_COUNT_ALLOW_BY_HEARTBEAT:
                    peer_info.status = PeerStatus.disconnected
                    logging.debug(f"peer status update time: {peer_info.status_update_time}")
                    logging.debug(f"this peer not respond {peer_info.peer_id}")
                    nonresponse_peer_list.append(peer_info)

        logging.info(f"non response peer list : {nonresponse_peer_list}")
示例#17
0
    def __handler_peer_list(self, request, context):
        channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel
        peer_manager = self.peer_service.channel_manager.get_peer_manager(
            channel_name)
        message = "All Group Peers count: " + str(
            len(peer_manager.peer_list[conf.ALL_GROUP_ID]))

        return loopchain_pb2.Message(code=message_code.Response.success,
                                     message=message,
                                     meta=str(peer_manager.peer_list))
示例#18
0
    def __handler_get_tx_by_address(self, request, context):
        """Get Transaction by address

        :param request:
        :param context:
        :return:
        """
        params = json.loads(request.meta)
        address = params.pop('address', None)
        index = params.pop('index', None)

        if address is None or index is None:  # or params:
            return loopchain_pb2.Message(code=message_code.Response.fail_illegal_params)

        channel_stub = StubCollection().channel_stubs[request.channel]
        tx_list, next_index = channel_stub.sync_task().get_tx_by_address(address, index)

        return loopchain_pb2.Message(code=message_code.Response.success,
                                     meta=str(next_index),
                                     object=pickle.dumps(tx_list))
示例#19
0
    def Request(self, request, context):
        logging.debug(f"rs_admin_service:Request({request})")
        logging.debug(f"get context : {context}")

        if request.code in self.__handler_map.keys():
            return self.__handler_map[request.code](request, context)

        logging.warning(
            f"rs_admin_service:Request not treat message code({request.code})")
        return loopchain_pb2.Message(
            code=message_code.Response.not_treat_message_code)
示例#20
0
    def __handler_peer_list(self, request, context):
        channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel

        channel_stub = StubCollection().channel_stubs[channel_name]
        all_group_peer_list_str, peer_list_str = channel_stub.sync_task().get_peer_list()

        message = "All Group Peers count: " + all_group_peer_list_str

        return loopchain_pb2.Message(
            code=message_code.Response.success,
            message=message,
            meta=peer_list_str)
示例#21
0
    def __handler_restart_channel(self, request, context):
        """

        :param request:
        :param context:
        :return:
        """
        util.logger.spam(f"rs_admin_service:__handler_restart_channel")

        message = loopchain_pb2.Message(
            code=message_code.Request.peer_restart_channel,
            channel=request.channel,
            message="restart channel")

        ObjectManager().rs_service.channel_manager.broadcast(
            request.channel,
            "Request",
            message,
            timeout=conf.CHANNEL_RESTART_TIMEOUT)

        return loopchain_pb2.Message(code=message_code.Response.success)
示例#22
0
    def __handler_get_total_supply(self, request, context):
        """Get Total Supply

        :param request:
        :param context:
        :return:
        """
        query_request = loopchain_pb2.QueryRequest(params=request.meta, channel=request.channel)
        response = self.Query(query_request, context)
        util.logger.spam(f"peer_outer_service:__handler_get_total_supply response({response})")

        return loopchain_pb2.Message(code=response.response_code, meta=response.response)
示例#23
0
    def __handler_status(self, request, context):
        util.logger.debug(f"peer_outer_service:handler_status")
        channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel
        status = dict()
        if ObjectManager().peer_service is not None:
            status['peer_type'] = \
                str(self.peer_service.channel_manager.get_block_manager(channel_name).peer_type)
        else:
            status['peer_type'] = '0'
        status_json = json.dumps(status)

        return loopchain_pb2.Message(code=message_code.Response.success,
                                     meta=status_json)
示例#24
0
    def Query(self, request, context):
        """Score 의 invoke 로 생성된 data 에 대한 query 를 수행한다."""
        channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel

        # TODO 입력값 오류를 검사하는 방법을 고려해본다, 현재는 json string 여부만 확인
        if util.check_is_json_string(request.params):
            logging.debug(f'Query request with {request.params}')
            try:
                response_from_score_service = \
                    self.peer_service.channel_manager.get_score_container_stub(channel_name).call(
                        method_name="Request",
                        message=loopchain_pb2.Message(code=message_code.Request.score_query, meta=request.params),
                        timeout=conf.SCORE_QUERY_TIMEOUT,
                        is_raise=True
                    )
                response = response_from_score_service.meta

                util.apm_event(
                    self.peer_service.peer_id, {
                        'event_type': 'Query',
                        'peer_id': self.peer_service.peer_id,
                        'data': {
                            'score_query': json.loads(request.params)
                        }
                    })

            except Exception as e:
                logging.error(f'Execute Query Error : {e}')
                if isinstance(e, _Rendezvous):
                    # timeout 일 경우
                    if e.code() == grpc.StatusCode.DEADLINE_EXCEEDED:
                        return loopchain_pb2.QueryReply(
                            response_code=message_code.Response.timeout_exceed,
                            response="")
                return loopchain_pb2.QueryReply(
                    response_code=message_code.Response.fail, response="")
        else:
            return loopchain_pb2.QueryReply(
                response_code=message_code.Response.fail_validate_params,
                response="")

        if util.check_is_json_string(response):
            # TODO 응답값 오류를 검사하는 방법을 고려해본다, 현재는 json string 여부만 확인
            response_code = message_code.Response.success
        else:
            response_code = message_code.Response.fail

        return loopchain_pb2.QueryReply(response_code=response_code,
                                        response=response)
    def __handler_rs_send_channel_manage_info_to_rs(self, request, context):
        """

        :param request.code: message_code.Request.rs_send_channel_manage_info_to_rs
        :param request.meta: channel_manage_info
        :param request.message: from gtool or another rs
        """
        util.logger.spam(
            f"rs_admin_service:__handler_rs_send_channel_manage_info_to_rs")

        # TODO rs 의 admin_manager 에 channel_manage_info 반영, 자신의 json 파일에도 반영

        # TODO 이 메시지가 gtool 에서 왔다면, 다른 rs 에도 전송한다.(rs 이중화 완료까지 보류) 이때는 메시지를 변경하여 출처를 gtool 이 아닌 rs 로 수정한다.

        return loopchain_pb2.Message(code=message_code.Response.success)
示例#26
0
    def __handler_delete_peer(self, request, context):
        util.logger.spam(
            f"rs_admin_service:__handler_delete_peer target({request.message})"
        )
        self.__admin_manager.save_channel_manage_data(json.loads(request.meta))

        peer_target = request.message
        channel_manager_data = json.loads(request.meta)
        channel_manager = ObjectManager().rs_service.channel_manager
        for channel in channel_manager_data:
            util.logger.spam(
                f"rs_admin_service:__handler_delete_peer channel({channel})")
            channel_manager.get_peer_manager(channel).\
                remove_peer_by_target(channel_manager, peer_target)

        return loopchain_pb2.Message(code=message_code.Response.success)
示例#27
0
    def __handler_rs_send_channel_manage_info_to_rs(self, request, context):
        """

        :param request.code: message_code.Request.rs_send_channel_manage_info_to_rs
        :param request.meta: channel_manage_info
        :param request.message: from gtool or another rs
        """
        util.logger.spam(
            f"rs_admin_service:__handler_rs_send_channel_manage_info_to_rs")

        self.__admin_manager.save_channel_manage_data(json.loads(request.meta))
        logging.debug(
            f"rs_admin_service:__handler_rs_send_channel_manage_info_to_rs "
            f"new channel_manage_data({self.__admin_manager.json_data})")

        return loopchain_pb2.Message(code=message_code.Response.success)
示例#28
0
    def __handler_get_tx_result(self, request, context):
        """Get Transaction Result for json-rpc request

        :param request:
        :param context:
        :return:
        """
        util.logger.spam(f"checking for test, code: {request.code}")
        util.logger.spam(f"checking for test, channel name: {request.channel}")
        util.logger.spam(f"checking for test, message: {request.message}")
        util.logger.spam(f"checking for test, meta: {json.loads(request.meta)}")

        params = json.loads(request.meta)

        util.logger.spam(f"params tx_hash({params['tx_hash']})")

        return loopchain_pb2.Message(code=message_code.Response.success)
示例#29
0
    def leader_complain_to_rs(self,
                              group_id,
                              is_announce_new_peer=True) -> PeerInfo:
        """When fail to find a leader, Ask to RS.
        RS check leader and notify leader info or set new leader first peer who complained

        :param group_id:
        :param is_announce_new_peer:
        :return:
        """
        logging.debug(f"peer_manager:leader_complain_to_rs")

        if ObjectManager().peer_service.stub_to_radiostation is None:
            return None

        peer_self = self.get_peer(ObjectManager().peer_service.peer_id,
                                  ObjectManager().peer_service.group_id)
        peer_self_dumped = peer_self.dump()
        response = ObjectManager().peer_service.stub_to_radiostation.call(
            "Request",
            loopchain_pb2.Message(
                code=message_code.Request.peer_complain_leader,
                message=group_id,
                object=peer_self_dumped))

        if response is not None and response.code == message_code.Response.success:
            try:
                leader_peer = PeerInfo.load(response.object)
            except Exception as e:
                traceback.print_exc()
                logging.error(
                    f"Invalid peer info. Check your Radio Station. exception={e}"
                )
                return None
            self.set_leader_peer(leader_peer)
        else:
            leader_peer = None

        # logging.debug(str(leader_peer))
        # self.set_leader_peer(leader_peer)
        #
        # if is_announce_new_peer:
        #     self.announce_new_leader("", leader_peer.peer_id)

        return leader_peer
示例#30
0
    def Stop(self, request, context):
        """Peer를 중지시킨다

        :param request: 중지요청
        :param context:
        :return: 중지결과
        """
        if request is not None:
            logging.info('Peer will stop... by: ' + request.reason)

        try:
            response = self.peer_service.stub_to_score_service.call(
                "Request",
                loopchain_pb2.Message(code=message_code.Request.stop))
            logging.debug("try stop score container: " + str(response))
        except Exception as e:
            logging.debug("Score Service Already stop by other reason. %s", e)

        self.peer_service.service_stop()
        return loopchain_pb2.StopReply(status="0")