def __load_score(self, score_package_name: str, score_container_stub: StubManager, peer_target: str): """스코어를 로드한다. :param score_package_name: score package name """ util.logger.spam(f"peer_service:__load_score --start--") logging.info("LOAD SCORE AND CONNECT TO SCORE SERVICE!") params = dict() params[message_code.MetaParams.ScoreLoad. repository_path] = conf.DEFAULT_SCORE_REPOSITORY_PATH params[message_code.MetaParams.ScoreLoad. score_package] = score_package_name params[ message_code.MetaParams.ScoreLoad.base] = conf.DEFAULT_SCORE_BASE params[message_code.MetaParams.ScoreLoad.peer_id] = \ None if ObjectManager().peer_service is None else ObjectManager().peer_service.peer_id meta = json.dumps(params) logging.debug(f"load score params : {meta}") if score_container_stub is None: util.exit_and_msg(f"there is no __stub_to_scoreservice!") util.logger.spam(f"peer_service:__load_score --1--") # Score Load is so slow ( load time out is more than GRPC_CONNECTION_TIMEOUT) response = score_container_stub.call( "Request", loopchain_pb2.Message(code=message_code.Request.score_load, meta=meta), conf.SCORE_LOAD_TIMEOUT) logging.debug("try score load on score service: " + str(response)) if response is None: return None util.logger.spam(f"peer_service:__load_score --2--") response_connect = score_container_stub.call( "Request", loopchain_pb2.Message(code=message_code.Request.score_connect, message=peer_target), conf.GRPC_CONNECTION_TIMEOUT) logging.debug("try connect to score service: " + str(response_connect)) if response_connect is None: return None if response.code == message_code.Response.success: logging.debug("Get Score from Score Server...") score_info = json.loads(response.meta) else: util.exit_and_msg("Fail Get Score from Score Server...") logging.info("LOAD SCORE DONE!") util.logger.spam(f"peer_service:__load_score --end--") return score_info
def get_next_leader_stub_manager(self, group_id=None): """다음 리더 peer, stub manager 을 식별한다. :param group_id: :return: peer, stub manager """ util.logger.spam(f"peer_manager:get_next_leader_stub_manager") if group_id is None: group_id = conf.ALL_GROUP_ID max_retry = self.get_peer_count(None) try_count = 0 next_leader_peer = self.__get_next_peer(self.get_leader_peer(group_id), group_id) while try_count < max_retry: stub_manager = StubManager(next_leader_peer.target, loopchain_pb2_grpc.PeerServiceStub, conf.GRPC_SSL_TYPE) try: try_count += 1 response = stub_manager.call( "GetStatus", loopchain_pb2.CommonRequest(request="")) logging.debug("Peer Status: " + str(response)) return next_leader_peer, stub_manager except Exception as e: logging.debug("try another stub..." + str(e)) next_leader_peer = self.__get_next_peer(next_leader_peer, group_id) logging.warning("fail found next leader stub") return None, None
def get_next_leader_stub_manager(self, group_id=None): """다음 리더 peer, stub manager 을 식별한다. :param group_id: :return: peer, stub manager """ # TODO 피어 재시작 후의 접속하는 피어의 connected 상태 변경 확인할 것 # connected peer 만 순회하도록 수정할 것, 현재는 확인 되지 않았으므로 전체 순회로 구현함 # max_retry = self.get_connected_peer_count(group_id) if group_id is None: group_id = conf.ALL_GROUP_ID max_retry = self.get_peer_count(None) try_count = 0 next_leader_peer = self.__get_next_peer(self.get_leader_peer(group_id), group_id) while try_count < max_retry: stub_manager = StubManager(next_leader_peer.target, loopchain_pb2_grpc.PeerServiceStub) try: try_count += 1 response = stub_manager.call("GetStatus", loopchain_pb2.CommonRequest(request="")) logging.debug("Peer Status: " + str(response)) return next_leader_peer, stub_manager except Exception as e: logging.debug("try another stub..." + str(e)) next_leader_peer = self.__get_next_peer(next_leader_peer, group_id) logging.warning("fail found next leader stub") return None, None
class ServerComponents(metaclass=SingletonMetaClass): def __init__(self): self.__app = Sanic(__name__) self.__app.config.KEEP_ALIVE = False # SSL 적용 여부에 따라 context 생성 여부를 결정한다. if conf.REST_SSL_TYPE is conf.SSLAuthType.none: self.__ssl_context = None elif conf.REST_SSL_TYPE == conf.SSLAuthType.server_only: self.__ssl_context = (conf.DEFAULT_SSL_CERT_PATH, conf.DEFAULT_SSL_KEY_PATH) elif conf.REST_SSL_TYPE == conf.SSLAuthType.mutual: self.__ssl_context = ssl.SSLContext(_ssl.PROTOCOL_SSLv23) self.__ssl_context.verify_mode = ssl.CERT_REQUIRED self.__ssl_context.check_hostname = False self.__ssl_context.load_verify_locations( cafile=conf.DEFAULT_SSL_TRUST_CERT_PATH) self.__ssl_context.load_cert_chain(conf.DEFAULT_SSL_CERT_PATH, conf.DEFAULT_SSL_KEY_PATH) else: utils.exit_and_msg( f"REST_SSL_TYPE must be one of [0,1,2]. But now conf.REST_SSL_TYPE is {conf.REST_SSL_TYPE}" ) @property def app(self): return self.__app @property def stub(self): return self.__stub_to_rs_service @property def ssl_context(self): return self.__ssl_context def set_stub_port(self, port): self.__stub_to_rs_service = StubManager( conf.IP_LOCAL + ':' + str(port), loopchain_pb2_grpc.RadioStationStub, ssl_auth_type=conf.GRPC_SSL_TYPE) def set_resource(self): self.__app.add_route(Peer.as_view(), '/api/v1/peer/<request_type:string>') self.__app.add_route(Configuration.as_view(), '/api/v1/conf') self.__app.add_route( Certificate.as_view(), '/api/v1/cert/<request_type:string>/<certificate_type:string>') def get_peer_list(self, channel): return self.__stub_to_rs_service.call( "GetPeerList", loopchain_pb2.CommonRequest(request="", group_id=conf.ALL_GROUP_ID, channel=channel)) def get_leader_peer(self, channel): return self.__stub_to_rs_service.call( "Request", loopchain_pb2.Message(code=message_code.Request.peer_get_leader, channel=channel)) def get_peer_status(self, peer_id, group_id, channel): return self.__stub_to_rs_service.call_in_times( "GetPeerStatus", loopchain_pb2.PeerID(peer_id=peer_id, group_id=group_id, channel=channel)) def get_peer_status_async(self, peer_id, group_id, channel) -> grpc.Future: return self.__stub_to_rs_service.call_async( "GetPeerStatus", loopchain_pb2.PeerID(peer_id=peer_id, group_id=group_id, channel=channel)) def get_configuration(self, conf_info): return self.__stub_to_rs_service.call( "Request", loopchain_pb2.Message( code=message_code.Request.rs_get_configuration, meta=conf_info)) def set_configuration(self, conf_info): return self.__stub_to_rs_service.call( "Request", loopchain_pb2.Message( code=message_code.Request.rs_set_configuration, meta=conf_info)) def response_simple_success(self): result = { 'response_code': message_code.Response.success, 'message': message_code.get_response_msg(message_code.Response.success) } return result def abort_if_url_doesnt_exist(self, request_type, type_list): result = {'response_code': message_code.Response.fail} if request_type not in type_list.values(): result['message'] = "The resource doesn't exist" return result def ready(self): async def ready_tasks(): from loopchain import loggers loggers.get_preset().update_logger() loggers.update_other_loggers() logging.debug('rest_server:initialize complete.') self.__app.add_task(ready_tasks()) def serve(self, api_port): self.ready() self.__app.run(host='0.0.0.0', port=api_port, debug=False, ssl=self.ssl_context)
class PeerServiceStub(metaclass=SingletonMetaClass): REST_GRPC_TIMEOUT = conf.GRPC_TIMEOUT + conf.REST_ADDITIONAL_TIMEOUT REST_SCORE_QUERY_TIMEOUT = conf.SCORE_QUERY_TIMEOUT + conf.REST_ADDITIONAL_TIMEOUT def __init__(self): self.__stub_to_peer_service = None def set_stub_port(self, port, IP_address): IP_address = conf.IP_LOCAL self.__stub_to_peer_service = StubManager( IP_address + ':' + str(port), loopchain_pb2_grpc.PeerServiceStub, conf.GRPC_SSL_TYPE) @property def stub(self): return self.__stub_to_peer_service def call(self, *args): # util.logger.spam(f"peer_service_stub:call target({self.__stub_to_peer_service.target})") return self.__stub_to_peer_service.call(*args) def get_status(self, channel: str): response = self.call("GetStatus", loopchain_pb2.StatusRequest(request="", channel=channel), self.REST_GRPC_TIMEOUT) status_json_data = json.loads(response.status) status_json_data['block_height'] = response.block_height status_json_data['unconfirmed_block_height'] = response.unconfirmed_block_height status_json_data['total_tx'] = response.total_tx status_json_data['leader_complaint'] = response.is_leader_complaining return status_json_data def get_last_block_hash(self, channel: str) -> str: response = self.call("GetLastBlockHash", loopchain_pb2.CommonRequest(request="", channel=channel), self.REST_GRPC_TIMEOUT) return str(response.block_hash) def get_block(self, channel: str, block_hash: str= "", block_height: int=-1): block_data_filter = "prev_block_hash, height, block_hash, merkle_tree_root_hash," \ " time_stamp, peer_id, signature" tx_data_filter = "icx_origin_data" response = self.call("GetBlock", loopchain_pb2.GetBlockRequest( block_hash=block_hash, block_height=block_height, block_data_filter=block_data_filter, tx_data_filter=tx_data_filter, channel=channel), self.REST_GRPC_TIMEOUT) return response def get_transaction(self, tx_hash: str, channel: str): return self.call("GetTx", loopchain_pb2.GetTxRequest(tx_hash=tx_hash, channel=channel), self.REST_GRPC_TIMEOUT) def get_invoke_result(self, tx_hash, channel): return self.call("GetInvokeResult", loopchain_pb2.GetInvokeResultRequest(tx_hash=tx_hash, channel=channel), self.REST_GRPC_TIMEOUT) def request(self, channel, code, params): response = self.call( "Request", loopchain_pb2.Message( code=code, channel=channel, meta=params ), self.REST_GRPC_TIMEOUT) try: response_data = json.loads(response.meta) except JSONDecodeError as e: response_data = json.loads("{}") response_data['response'] = response.meta response_data['response_code'] = response.code return response_data