Exemple #1
0
 def __make_peer_info(self, peer_id, group_id):
     peer_info = loopchain_pb2.PeerRequest()
     peer_info.peer_target = peer_id + "_target"
     peer_info.peer_type = loopchain_pb2.PEER
     peer_info.peer_id = peer_id
     peer_info.group_id = group_id
     return peer_info
Exemple #2
0
 def __subscribe_to_peer_list(self):
     peer_object = self.peer_manager.get_peer(ChannelProperty().peer_id)
     peer_request = loopchain_pb2.PeerRequest(
         channel=ChannelProperty().name,
         peer_target=ChannelProperty().peer_target,
         peer_id=ChannelProperty().peer_id, group_id=ChannelProperty().group_id,
         node_type=ChannelProperty().node_type,
         peer_order=peer_object.order
     )
     self.__broadcast_scheduler.schedule_broadcast("Subscribe", peer_request)
Exemple #3
0
 async def __subscribe_call_to_stub(self, peer_stub, peer_type):
     if self.is_support_node_function(conf.NodeFunction.Vote):
         await peer_stub.call_async(
             "Subscribe",
             loopchain_pb2.PeerRequest(
                 channel=ChannelProperty().name,
                 peer_target=ChannelProperty().peer_target, peer_type=peer_type,
                 peer_id=ChannelProperty().peer_id, group_id=ChannelProperty().group_id,
                 node_type=ChannelProperty().node_type
             ),
         )
     else:
         await self.__subscribe_call_from_citizen()
Exemple #4
0
    async def __subscribe_call_to_stub_by_method(self, peer_stub, peer_type):
        if self.is_support_node_function(conf.NodeFunction.Vote):
            await peer_stub.call_async(
                "Subscribe",
                loopchain_pb2.PeerRequest(
                    channel=ChannelProperty().name,
                    peer_target=ChannelProperty().peer_target, peer_type=peer_type,
                    peer_id=ChannelProperty().peer_id, group_id=ChannelProperty().group_id,
                    node_type=ChannelProperty().node_type
                ),
            )
        else:
            util.logger.spam(f"channel_service:__subscribe_call_to_stub_by_method "
                             f"peer_target({ChannelProperty().rest_target})")
            response = self.__subscribe_call_to_rs_stub(peer_stub)

            if response['response_code'] != message_code.Response.success:
                error = f"subscribe fail to peer_target({ChannelProperty().radio_station_target}) " \
                        f"reason({response['message']})"
                await StubCollection().peer_stub.async_task().stop(message=error)
Exemple #5
0
    def __connect_to_radiostation(self):
        """RadioStation 접속

        :return: 접속정보, 실패시 None
        """
        logging.debug("try to connect to radiostation")

        self.__stub_to_radio_station = StubManager.get_stub_manager_to_server(
            self.__radio_station_target, loopchain_pb2_grpc.RadioStationStub,
            conf.CONNECTION_RETRY_TIMEOUT_TO_RS)

        if self.__stub_to_radio_station is None:
            logging.warning("fail make stub to Radio Station!!")
            return None

        token = None
        if self.__auth.is_secure:
            peer_self = self.__peer_manager.get_peer(self.peer_id)
            token = None
            if peer_self is not None:
                token = peer_self.token
            logging.debug("Self Peer Token : %s", token)

            # 토큰 유효시간이 지나면 다시 생성 요청
            if token is not None and self.__auth.get_token_time(token) is None:
                token = None

            self.__auth.set_peer_info(self.peer_id, self.__peer_target,
                                      self.group_id, self.__peer_type)
            cert_bytes = self.__auth.get_cert_bytes()
            if token is None:
                # 서버로부터 난수 수신
                # response = util.request_server_in_time(self.__stub_to_radio_station.ConnectPeer,
                #                                        loopchain_pb2.PeerRequest(
                #                                            peer_object=b'',
                #                                            peer_id=self.peer_id,
                #                                            peer_target=self.__peer_target,
                #                                            group_id=self.group_id,
                #                                            peer_type=self.__peer_type,
                #                                            token=conf.TOKEN_TYPE_CERT + cert_bytes.hex())
                #                                        )
                response = self.__stub_to_radio_station.call(
                    "ConnectPeer",
                    loopchain_pb2.PeerRequest(peer_object=b'',
                                              peer_id=self.peer_id,
                                              peer_target=self.__peer_target,
                                              group_id=self.group_id,
                                              peer_type=self.__peer_type,
                                              token=conf.TOKEN_TYPE_CERT +
                                              cert_bytes.hex()),
                    conf.GRPC_TIMEOUT)

                rand_key = None
                if response is not None and response.status == message_code.Response.success:
                    logging.debug("Received Random : %s", response.more_info)
                    if len(response.more_info) is not 32:
                        # 토큰 크기가 16바이트가 아니면 접속을 할 수 없습니다.
                        logging.debug('서버로부터 수신한 토큰 길이는 16바이트가 되어야 합니다.')
                    else:
                        rand_key = response.more_info
                else:
                    return response

                # 난수와 Peer 정보에 서명
                if rand_key is None:
                    return None
                else:
                    sign = self.__auth.generate_request_sign(rand_key=rand_key)
                    token = conf.TOKEN_TYPE_SIGN + sign.hex()
            else:
                self.__auth.add_token(token)

        # 공통 부분
        # response = util.request_server_in_time(self.__stub_to_radio_station.ConnectPeer,
        #                                        loopchain_pb2.PeerRequest(
        #                                            peer_object=b'',
        #                                            peer_id=self.peer_id,
        #                                            peer_target=self.__peer_target,
        #                                            group_id=self.group_id,
        #                                            peer_type=self.__peer_type,
        #                                            token=token
        #                                        ))
        response = self.__stub_to_radio_station.call(
            "ConnectPeer",
            loopchain_pb2.PeerRequest(peer_object=b'',
                                      peer_id=self.peer_id,
                                      peer_target=self.__peer_target,
                                      group_id=self.group_id,
                                      peer_type=self.__peer_type,
                                      token=token),
            conf.GRPC_CONNECTION_TIMEOUT)

        if response is not None and response.status == message_code.Response.success:
            if self.__auth.is_secure:
                logging.debug("Received Token : %s", response.more_info)
                # Radiostation으로부터 수신한 토큰 검증
                if len(response.more_info) < 9:
                    # 토큰 크기가 8 + 1바이트 보다 크지 아니면 접속을 할 수 없습니다.
                    logging.debug('서버로부터 수신한 토큰 길이는 9바이트 이상이 되어야 합니다.')
                    response.status = message_code.Response.fail_validate_params
                    response.more_info = "Invalid Token Data"
                else:
                    token = response.more_info
                    tag = token[:2]
                    if tag == conf.TOKEN_TYPE_TOKEN:
                        if self.__auth.verify_token(token):
                            logging.debug("토큰 검증에 성공하였습니다.")
                            self.__auth.add_token(token)
                        else:
                            logging.debug("토큰 검증에 실패하였습니다.")
                            response.status = message_code.Response.fail_validate_params
                            response.more_info = "Invalid Token Signature"

        return response
Exemple #6
0
    def __connect_to_radiostation(self):
        """RadioStation 접속

        :return: 접속정보, 실패시 None
        """
        logging.debug("try to connect to radiostation")

        self.__stub_to_radio_station = StubManager.get_stub_manager_to_server(
            self.__radio_station_target, loopchain_pb2_grpc.RadioStationStub,
            conf.CONNECTION_RETRY_TIMEOUT_TO_RS)

        if self.__stub_to_radio_station is None:
            logging.warning("fail make stub to Radio Station!!")
            return None

        token = None
        if self.__auth.is_secure:
            self.__peer_object = self.__peer_manager.get_peer(self.peer_id)
            token = None
            if self.__peer_object is not None:
                token = self.__peer_object.token
            logging.debug("Self Peer Token : %s", token)

            # 토큰 유효시간이 지나면 다시 생성 요청
            if token is not None and self.__auth.get_token_time(token) is None:
                token = None

            self.__auth.set_peer_info(self.peer_id, self.__peer_target,
                                      self.group_id, self.__peer_type)
            cert_bytes = self.__auth.get_cert_bytes()
            if token is None:
                # 서버로부터 난수 수신
                # response = util.request_server_in_time(self.__stub_to_radio_station.ConnectPeer,
                #                                        loopchain_pb2.PeerRequest(
                #                                            peer_object=b'',
                #                                            peer_id=self.peer_id,
                #                                            peer_target=self.__peer_target,
                #                                            group_id=self.group_id,
                #                                            peer_type=self.__peer_type,
                #                                            token=conf.TOKEN_TYPE_CERT + cert_bytes.hex())
                #                                        )
                response = self.__stub_to_radio_station.call(
                    "ConnectPeer",
                    loopchain_pb2.PeerRequest(peer_object=b'',
                                              peer_id=self.peer_id,
                                              peer_target=self.__peer_target,
                                              group_id=self.group_id,
                                              peer_type=self.__peer_type,
                                              token=conf.TOKEN_TYPE_CERT +
                                              cert_bytes.hex()),
                    conf.GRPC_TIMEOUT)

                rand_key = None
                if response is not None and response.status == message_code.Response.success:
                    logging.debug("Received Random : %s", response.more_info)
                    if len(response.more_info) is not 32:
                        # 토큰 크기가 16바이트가 아니면 접속을 할 수 없습니다.
                        logging.debug('서버로부터 수신한 토큰 길이는 16바이트가 되어야 합니다.')
                    else:
                        rand_key = response.more_info
                else:
                    return response

                # 난수와 Peer 정보에 서명
                if rand_key is None:
                    return None
                else:
                    sign = self.__auth.generate_request_sign(rand_key=rand_key)
                    token = conf.TOKEN_TYPE_SIGN + sign.hex()
            else:
                self.__auth.add_token(token)

        # 공통 부분
        # response = util.request_server_in_time(self.__stub_to_radio_station.ConnectPeer,
        #                                        loopchain_pb2.PeerRequest(
        #                                            peer_object=b'',
        #                                            peer_id=self.peer_id,
        #                                            peer_target=self.__peer_target,
        #                                            group_id=self.group_id,
        #                                            peer_type=self.__peer_type,
        #                                            token=token
        #                                        ))
        response = self.__stub_to_radio_station.call(
            "ConnectPeer",
            loopchain_pb2.PeerRequest(peer_object=b'',
                                      peer_id=self.peer_id,
                                      peer_target=self.__peer_target,
                                      group_id=self.group_id,
                                      peer_type=self.__peer_type,
                                      token=token),
            conf.GRPC_CONNECTION_TIMEOUT)

        if response is not None and response.status == message_code.Response.success:
            if self.__auth.is_secure:
                logging.debug("Received Token : %s", response.more_info)
                # Radiostation으로부터 수신한 토큰 검증
                if len(response.more_info) < 9:
                    # 토큰 크기가 8 + 1바이트 보다 크지 아니면 접속을 할 수 없습니다.
                    logging.debug('서버로부터 수신한 토큰 길이는 9바이트 이상이 되어야 합니다.')
                    response.status = message_code.Response.fail_validate_params
                    response.more_info = "Invalid Token Data"
                else:
                    token = response.more_info
                    tag = token[:2]
                    if tag == conf.TOKEN_TYPE_TOKEN:
                        if self.__auth.verify_token(token):
                            logging.debug("토큰 검증에 성공하였습니다.")
                            self.__auth.add_token(token)
                        else:
                            logging.debug("토큰 검증에 실패하였습니다.")
                            response.status = message_code.Response.fail_validate_params
                            response.more_info = "Invalid Token Signature"

        logging.debug("Connect to radiostation: " + str(response))

        is_peer_list_from_rs = False

        if response is not None and response.status == message_code.Response.success:
            # RS 의 응답이 있으면 peer_list 는 RS 가 전달한 결과로 업데이트 된다.
            # 없는 경우 local 의 level DB 로 부터 읽어드린 값을 default 로 사용하게 된다.
            # TODO RS 는 어떻게 신뢰하지? RS 가 새로운 피어의 참여를 승인하더라도 참여한 피어 목록은 더 신뢰할만한 방식으로 보호가 필요하지 않나?
            # 누군가 RS 를 죽인다면 RS 인척 가짜로 이루어진 피어 리스트를 전송하면 네트워크를 파괴할 수 있지 않나?
            # 피어의 참여는 RS 가 승인한 다음 블록에 담아서 블록체인에 추가하면 어떨까?

            peer_list_data = pickle.loads(response.peer_list)
            self.__peer_manager.load(peer_list_data, False)
            self.__common_service.save_peer_list(self.__peer_manager)
            logging.debug("peer list update: " +
                          self.__peer_manager.get_peers_for_debug())
            is_peer_list_from_rs = True
        else:
            logging.debug("using local peer list: " +
                          self.__peer_manager.get_peers_for_debug())

        return is_peer_list_from_rs