def __handler_connect_to_leader(self, request, context): logging.debug( f"TxService handler connect to leader({request.message})") leader_target = request.message self.__stub_to_leader = StubManager.get_stub_manager_to_server( leader_target, loopchain_pb2_grpc.PeerServiceStub, time_out_seconds=conf.CONNECTION_RETRY_TIMEOUT, is_allow_null_stub=True) self.__peer_status = PeerProcessStatus.normal # TODO block generator 연결 실패 조건 확인할 것 if self.__stub_to_leader is None: return loopchain_pb2.Message( code=message_code.Response.fail_connect_to_leader) else: try: self.__create_tx_continue() except Exception as e: logging.warning( "in tx service create tx continue() Exception: " + str(e)) self.__peer_status = PeerProcessStatus.leader_complained return loopchain_pb2.Message( code=message_code.Response.fail_add_tx_to_leader) return loopchain_pb2.Message(code=message_code.Response.success)
async def score_load(self, params): logging.debug(f"ScoreService Score Load Request : {params}") for i in range(conf.SCORE_GIT_LOAD_RETRY_TIMES): try: params = json.loads(params) self._score_service.peer_id = params[message_code.MetaParams.ScoreLoad.peer_id] util.logger.spam(f"score_service:__handler_score_load try init PeerScore") self._score_service.score = PeerScore(params[message_code.MetaParams.ScoreLoad.repository_path], params[message_code.MetaParams.ScoreLoad.score_package], params[message_code.MetaParams.ScoreLoad.base]) util.logger.spam(f"score_service:__handler_score_load after init PeerScore") score_info = dict() score_info[message_code.MetaParams.ScoreInfo.score_id] = self._score_service.score.id() score_info[message_code.MetaParams.ScoreInfo.score_version] = self._score_service.score.version() meta = json.dumps(score_info) return loopchain_pb2.Message(code=message_code.Response.success, meta=meta) except git.exc.GitCommandError as e: logging.exception(f"score_service:__handler_score_load SCORE LOAD IS FAIL params({params}) error({e})") logging.info("You may use restarting channel. " "It is because of peers in your machine access git repository at same time.") time.sleep(conf.SCORE_GIT_LOAD_SLEEP + random.uniform(-1.0, 1.0)) except Exception as e: logging.exception(f"score_service:__handler_score_load SCORE LOAD IS FAIL params({params}) error({e})") return loopchain_pb2.Message(code=message_code.Response.fail, message=str(e))
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] # FIXME : is need? if conf.ENABLE_REP_RADIO_STATION and 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 !") status_json = json.dumps(status) return loopchain_pb2.Message(code=message_code.Response.success, meta=status_json)
def __handler_score_load(self, request, context): logging.debug(f"ScoreService Score Load Request : {request}") try: params = json.loads(request.meta) self.__peer_id = params[message_code.MetaParams.ScoreLoad.peer_id] util.logger.spam( f"score_service:__handler_score_load try init PeerScore") self.__score = PeerScore( params[message_code.MetaParams.ScoreLoad.repository_path], params[message_code.MetaParams.ScoreLoad.score_package], params[message_code.MetaParams.ScoreLoad.base]) util.logger.spam( f"score_service:__handler_score_load after init PeerScore") score_info = dict() score_info[message_code.MetaParams.ScoreInfo. score_id] = self.__score.id() score_info[message_code.MetaParams.ScoreInfo. score_version] = self.__score.version() meta = json.dumps(score_info) return loopchain_pb2.Message(code=message_code.Response.success, meta=meta) except Exception as e: logging.exception( f"score_service:__handler_score_load SCORE LOAD IS FAIL params({params}) error({e})" ) return loopchain_pb2.Message(code=message_code.Response.fail, message=str(e))
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] future = asyncio.run_coroutine_threadsafe( channel_stub.async_task().get_tx_by_address(address, index), self.peer_service.inner_service.loop) tx_list, next_index = future.result() tx_list_dumped = json.dumps(tx_list).encode( encoding=conf.PEER_DATA_ENCODING) return loopchain_pb2.Message(code=message_code.Response.success, meta=str(next_index), object=tx_list_dumped)
def __handler_score_query(self, request, context): """ do query using request.meta and return json.dumps response :param request: :return: gRPC response """ logging.debug("ScoreService handler query...") if self.__score is None: logging.error("There is no score!!") ret = "" else: try: ret = self.__score.query(request.meta) except Exception as e: logging.error(f'query {request.meta} raise exception {e}') exception_response = { 'code': ScoreResponse.EXCEPTION, 'message': f'Query Raise Exception : {e}' } ret = json.dumps(exception_response) return loopchain_pb2.Message( code=message_code.Response.success, meta=ret) return loopchain_pb2.Message(code=message_code.Response.success, meta=ret)
def __handler_score_invoke(self, request, context): logging.debug("ScoreService handler invoke...") results = {} # dict key # TODO score invoke 관련 code, message 등을 별도의 파일로 정의하면 아래의 define 도 옮길것! code_key = 'code' error_message_key = 'message' if self.__score is None: logging.error("There is no score!!") return loopchain_pb2.Message(code=message_code.Response.fail) else: block = pickle.loads(request.object) logging.debug('tx_list_length : %d ', len(block.confirmed_transaction_list)) for transaction in block.confirmed_transaction_list: if isinstance( transaction, Transaction) and transaction.get_tx_hash() is not None: tx_hash = transaction.get_tx_hash() results[tx_hash] = {} # put score invoke result to results[tx_hash] try: invoke_result = self.__score.invoke(transaction, block) if invoke_result is None: results[tx_hash] = { 'code': message_code.Response.success } # logging.debug(f"handler_score_invoke: ({invoke_result})") else: if code_key not in invoke_result: code_not_return = "Score not return code" if error_message_key in invoke_result: raise ScoreInvokeError( code_not_return + ": " + invoke_result[error_message_key]) raise ScoreInvokeError(code_not_return) elif error_message_key in invoke_result: results[tx_hash][ error_message_key] = invoke_result[ error_message_key] results[tx_hash][code_key] = invoke_result[ code_key] # if score raise exception result to fail and put error message except Exception as e: logging.error("tx %s score invoke is fail!! : %s ", str(tx_hash), e) results[tx_hash][code_key] = ScoreResponse.EXCEPTION results[tx_hash][error_message_key] = str(e) continue # logging.debug('results : %s', str(results)) meta = json.dumps(results) return loopchain_pb2.Message(code=message_code.Response.success, meta=meta)
def __load_score(self, score): """스코어를 로드한다. :param score: score package name """ if self.__score_info is None: 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 params[message_code.MetaParams.ScoreLoad. base] = conf.DEFAULT_SCORE_BASE params[message_code.MetaParams.ScoreLoad.peer_id] = self.__peer_id meta = json.dumps(params) if self.__stub_to_score_service is None: logging.error(f"there is no __stub_to_scoreservice!") return False # Score Load is so slow ( load time out is more than GRPC_CONNECTION_TIMEOUT) response = self.__stub_to_score_service.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)) response_connect = self.__stub_to_score_service.call( "Request", loopchain_pb2.Message(code=message_code.Request.score_connect, message=self.__peer_target), conf.GRPC_CONNECTION_TIMEOUT) logging.debug("try connect to score service: " + str(response_connect)) if response.code == message_code.Response.success: logging.debug("Get Score from Score Server...") self.__score_info = json.loads(response.meta) else: logging.error("Fail Get Score from Score Server...") return False logging.info("LOAD SCORE DONE!") else: logging.info( "PEER SERVICE HAS SCORE BUT LOAD SCORE FUNCTION CALL!") score_dump = pickle.dumps(self.__score) response = self.__stub_to_score_service.call( "Request", loopchain_pb2.Message(code=message_code.Request.score_set, object=score_dump)) if response.code != message_code.Response.success: logging.error("Fail Set Score!!") logging.info("LOAD SCORE DONE!") return True
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 write_precommit_state(self, params): with self.__precommit_usage_lock: try: commit_request = json.loads(params) ScoreHelper().commit_block_state(commit_request['block_height'], commit_request['block_hash']) self.__remove_temp_invoke_results(commit_request['block_height']) return loopchain_pb2.Message(code=message_code.Response.success) except Exception as e: logging.exception(f"score db commit error : {params}\n" f"cause : {e}") util.exit_and_msg("score db commit fail") return loopchain_pb2.Message(code=message_code.Response.fail)
def Query(self, request, context): """Score 의 invoke 로 생성된 data 에 대한 query 를 수행한다. """ # TODO 입력값 오류를 검사하는 방법을 고려해본다, 현재는 json string 여부만 확인 if util.check_is_json_string(request.params): try: response_from_score_service = self.peer_service.stub_to_score_service.call( "Request", loopchain_pb2.Message( code=message_code.Request.score_query, meta=request.params)) response = response_from_score_service.meta except Exception as e: response = str(e) 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 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)
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)
def menu4_12(params): peer_stub = params[0] response = peer_stub.Request( loopchain_pb2.Message(code=message_code.Request.peer_peer_list), conf.GRPC_TIMEOUT) print("Peer Status: " + str(response)) menu4(peer_stub)
def GetScoreStatus(self, request, context): """Score Service 의 현재 상태를 요청 한다 :param request: :param context: :return: """ logging.debug("Peer GetScoreStatus request : %s", request) score_status = json.loads("{}") try: score_status_response = self.peer_service.stub_to_score_service.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 __handler_create_tx(self, request, context): # logging.debug("TxService handler create tx") tx = request.object tx_object = pickle.loads(tx) # logging.debug(f"TxService got tx({tx_object.get_tx_hash()})") try: if self.__peer_status == PeerProcessStatus.leader_complained: self.__stored_tx.put(tx) logging.warning( "Leader is complained your tx just stored in queue by temporally: " + str(self.__stored_tx.qsize())) else: self.__create_tx_continue() result_add_tx = self.__stub_to_leader.call( "AddTx", loopchain_pb2.TxSend(tx=tx), is_stub_reuse=True) if result_add_tx.response_code != message_code.Response.success: raise Exception(result_add_tx.message) except Exception as e: logging.warning( f"in tx service create_tx target({self.__stub_to_leader.target}) Exception: " + str(e)) self.__stored_tx.put(tx) self.__peer_status = PeerProcessStatus.leader_complained # TODO leader complain 방식 변경중 임시로 현재 트리거는 중단한다. # stub_to_self_peer.call_in_time( # "NotifyLeaderBroken", # loopchain_pb2.CommonRequest(request="Fail Add Tx to Leader") # ) return loopchain_pb2.Message(code=message_code.Response.success)
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))
def get_stub_manager_to_server(target, stub_class, time_out_seconds=None, is_allow_null_stub=False, ssl_auth_type=conf.SSLAuthType.none): """gRPC connection to server :return: stub manager to server """ if time_out_seconds is None: time_out_seconds = conf.CONNECTION_RETRY_TIMEOUT stub_manager = StubManager(target, stub_class, ssl_auth_type) start_time = timeit.default_timer() duration = timeit.default_timer() - start_time while duration < time_out_seconds: try: logging.debug("(stub_manager) get stub to server target: " + str(target)) stub_manager.stub.Request(loopchain_pb2.Message( code=message_code.Request.status, message="get_stub_manager_to_server"), conf.GRPC_TIMEOUT) return stub_manager except Exception as e: if is_allow_null_stub: return stub_manager logging.warning("Connect to Server Error(get_stub_manager_to_server): " + str(e)) logging.debug("duration(" + str(duration) + ") interval(" + str(conf.CONNECTION_RETRY_INTERVAL) + ") timeout(" + str(time_out_seconds) + ")") # RETRY_INTERVAL 만큼 대기후 TIMEOUT 전이면 다시 시도 time.sleep(conf.CONNECTION_RETRY_INTERVAL) duration = timeit.default_timer() - start_time return None
def get_stub_to_server(target, stub_class, time_out_seconds=None, is_check_status=True, ssl_auth_type: conf.SSLAuthType=conf.SSLAuthType.none): """gRPC connection to server :return: stub to server """ if time_out_seconds is None: time_out_seconds = conf.CONNECTION_RETRY_TIMEOUT stub = None channel = None start_time = timeit.default_timer() duration = timeit.default_timer() - start_time while stub is None and duration < time_out_seconds: try: logging.debug("(util) get stub to server target: " + str(target)) channel = GRPCHelper().create_client_channel(target, ssl_auth_type, conf.GRPC_SSL_KEY_LOAD_TYPE) stub = stub_class(channel) if is_check_status: stub.Request(loopchain_pb2.Message(code=message_code.Request.status), conf.GRPC_TIMEOUT) except Exception as e: logging.warning("Connect to Server Error(get_stub_to_server): " + str(e)) logging.debug("duration(" + str(duration) + ") interval(" + str(conf.CONNECTION_RETRY_INTERVAL) + ") timeout(" + str(time_out_seconds) + ")") # RETRY_INTERVAL 만큼 대기후 TIMEOUT 전이면 다시 시도 time.sleep(conf.CONNECTION_RETRY_INTERVAL) duration = timeit.default_timer() - start_time stub = None return stub, channel
def __handler_status(self, request, context): """Score Status 스코어의 정보 확인 + peer_service id + peer_service version + peer_service all_version + TODO last invoked block hash :param request: :param context: :return: """ logging.debug("score_service handler_status") status = dict() if self.__score is not None: status['id'] = self.__score.id() status['version'] = self.__score.version() status['all_version'] = self.__score.all_version() # TODO 외부에서 보는 GetStatus, ScoreStatus 에 대한 Status 값은 별도 정의가 필요하다. 현재는 임시 사용. status['status'] = message_code.Response.success else: status['status'] = message_code.Response.fail status_json = json.dumps(status) logging.debug("ScoreService __handler_status %s : %s", request.message, status_json) return loopchain_pb2.Message(code=message_code.Response.success, meta=status_json)
def get_stub_to_server(target, stub_class, time_out_seconds=conf.CONNECTION_RETRY_TIMEOUT, is_check_status=True): """gRPC connection to server :return: stub to server """ stub = None start_time = timeit.default_timer() duration = timeit.default_timer() - start_time while stub is None and duration < time_out_seconds: try: logging.debug("(util) get stub to server target: " + str(target)) channel = grpc.insecure_channel(target) stub = stub_class(channel) if is_check_status: stub.Request( loopchain_pb2.Message(code=message_code.Request.status), conf.GRPC_TIMEOUT) except Exception as e: logging.warning("Connect to Server Error(get_stub_to_server): " + str(e)) logging.debug("duration(" + str(duration) + ") interval(" + str(conf.CONNECTION_RETRY_INTERVAL) + ") timeout(" + str(time_out_seconds) + ")") # RETRY_INTERVAL 만큼 대기후 TIMEOUT 전이면 다시 시도 time.sleep(conf.CONNECTION_RETRY_INTERVAL) duration = timeit.default_timer() - start_time stub = None return stub
def check_status(self): try: self.__stub.Request(loopchain_pb2.Message(code=message_code.Request.status), conf.GRPC_TIMEOUT) return True except Exception as e: logging.warning(f"stub_manager:check_status is Fail reason({e})") return False
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().channel_service.connect_to_radio_station( is_reconnect=True) return loopchain_pb2.Message(code=message_code.Response.success)
def Request(self, request, context): # logging.debug("ScoreService 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)
def change_block_hash(self, params): with self.__precommit_usage_lock: try: change_block_info = json.loads(params) ScoreHelper().change_block_hash(block_height=change_block_info['block_height'], old_block_hash=change_block_info['old_block_hash'], new_block_hash=change_block_info['new_block_hash']) self.__remove_fail_invoke_result_to_new_block_invoke_result(change_block_info) return loopchain_pb2.Message(code=message_code.Response.success) except Exception as e: logging.exception(f"score change block hash fail : {params}\n" f"cause : {e}") # change block_hash fail often because next block commit # util.exit_and_msg("score db proxy change block_hash fail please restart") return loopchain_pb2.Message(code=message_code.Response.fail)
def __handler_score_load(self, request, context): logging.debug("ScoreService handler load...") try: params = json.loads(request.meta) self.__peer_id = params[message_code.MetaParams.ScoreLoad.peer_id] self.__score = PeerScore(params[message_code.MetaParams.ScoreLoad.repository_path], params[message_code.MetaParams.ScoreLoad.score_package], params[message_code.MetaParams.ScoreLoad.base]) score_info = dict() score_info[message_code.MetaParams.ScoreInfo.score_id] = self.__score.id() score_info[message_code.MetaParams.ScoreInfo.score_version] = self.__score.version() meta = json.dumps(score_info) return loopchain_pb2.Message(code=message_code.Response.success, meta=meta) except Exception as e: logging.error('__handler_score_load SCORE LOAD IS FAIL %s', str(e)) return loopchain_pb2.Message(code=message_code.Response.fail, message=str(e))
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)
def score_invoke(self, block): block_object = pickle.dumps(block) response = self.__stub_to_score_service.call( method_name="Request", message=loopchain_pb2.Message( code=message_code.Request.score_invoke, object=block_object), timeout=conf.SCORE_INVOKE_TIMEOUT, is_raise=True) # logging.debug("Score Server says: " + str(response)) if response.code == message_code.Response.success: return json.loads(response.meta)
def __handler_connect(self, request, context): """make stub to peer service :param request: message=target of peer_service :param context: :return: """ logging.debug("__handler_connect %s", request.message) self.__stub_to_peer_service = loopchain_pb2_grpc.PeerServiceStub(grpc.insecure_channel(request.message)) return_code = (message_code.Response.success, message_code.Response.fail)[self.__stub_to_peer_service is None] return loopchain_pb2.Message(code=return_code)
def __handler_score_query(self, request, context): logging.debug("ScoreService handler query...") if self.__score is None: logging.error("There is no score!!") ret = "" else: ret = self.__score.query(request.meta) return loopchain_pb2.Message(code=message_code.Response.success, meta=ret)