def menu4_1(params=None): admin_manager = AdminManager("demotool") print("\nInput Peer Target [IP]:[port] (default '' -> 127.0.0.1:7100, [port] -> 127.0.0.1:[port])") choice = input(" >> ") if choice == "": choice = "127.0.0.1:7100" elif choice.find(':') == -1: choice = "127.0.0.1:" + choice select_channel_index = 0 select_channel_string = "" for channel in admin_manager.get_channel_list(): if select_channel_index != 0: select_channel_string += ", " select_channel_string += f"{select_channel_index}: {admin_manager.get_channel_list()[select_channel_index]}" select_channel_index += 1 print(f"Select Channel ({select_channel_string})") channel_choice = input(" >> ") try: test_globals["channel_name"] = admin_manager.get_channel_list()[int(channel_choice)] except Exception as e: print(f"wrong channel number! Now use default channel({admin_manager.get_channel_list()[0]})\n") test_globals["channel_name"] = admin_manager.get_channel_list()[0] print("your input: " + choice) channel = grpc.insecure_channel(choice) peer_stub = loopchain_pb2_grpc.PeerServiceStub(channel) response = peer_stub.GetStatus(loopchain_pb2.StatusRequest(request="hello"), conf.GRPC_TIMEOUT) print("Peer Status: " + str(response)) menu4(peer_stub)
def __get_peer_stub_list(self): """It updates peer list for block manager refer to peer list on the loopchain network. This peer list is not same to the peer list of the loopchain network. :return max_height: a height of current blockchain :return peer_stubs: current peer list on the loopchain network """ max_height = -1 # current max height unconfirmed_block_height = -1 peer_stubs = [] # peer stub list for block height synchronization if not ObjectManager().channel_service.is_support_node_function( conf.NodeFunction.Vote): rest_stub = ObjectManager().channel_service.radio_station_stub peer_stubs.append(rest_stub) last_block = rest_stub.call("GetLastBlock") max_height = self.__blockchain.block_versioner.get_height( last_block) return max_height, unconfirmed_block_height, peer_stubs # Make Peer Stub List [peer_stub, ...] and get max_height of network peer_target = ChannelProperty().peer_target peer_manager = ObjectManager().channel_service.peer_manager target_dict = peer_manager.get_IP_of_peers_dict() target_list = [ peer_target for peer_id, peer_target in target_dict.items() if peer_id != ChannelProperty().peer_id ] for target in target_list: if target != peer_target: logging.debug(f"try to target({target})") channel = GRPCHelper().create_client_channel(target) stub = loopchain_pb2_grpc.PeerServiceStub(channel) try: response = stub.GetStatus( loopchain_pb2.StatusRequest( request="", channel=self.__channel_name, ), conf.GRPC_TIMEOUT_SHORT) response.block_height = max( response.block_height, response.unconfirmed_block_height) if response.block_height > max_height: # Add peer as higher than this max_height = response.block_height unconfirmed_block_height = response.unconfirmed_block_height peer_stubs.append(stub) except Exception as e: logging.warning( f"This peer has already been removed from the block height target node. {e}" ) return max_height, unconfirmed_block_height, peer_stubs
def __get_peer_stub_list(self, target_peer_stub=None): """It updates peer list for block manager refer to peer list on the loopchain network. This peer list is not same to the peer list of the loopchain network. :return max_height: a height of current blockchain :return peer_stubs: current peer list on the loopchain network """ peer_target = ChannelProperty().peer_target peer_manager = ObjectManager().channel_service.peer_manager # Make Peer Stub List [peer_stub, ...] and get max_height of network max_height = -1 # current max height peer_stubs = [] # peer stub list for block height synchronization if ObjectManager().channel_service.is_support_node_function( conf.NodeFunction.Vote): target_dict = peer_manager.get_IP_of_peers_dict() target_list = [ peer_target for peer_id, peer_target in target_dict.items() if peer_id != ChannelProperty().peer_id ] else: target_list = [f"{target_peer_stub.target}"] for target in target_list: if target != peer_target: logging.debug(f"try to target({target})") channel = GRPCHelper().create_client_channel(target) stub = loopchain_pb2_grpc.PeerServiceStub(channel) try: if ObjectManager( ).channel_service.is_support_node_function( conf.NodeFunction.Vote): response = stub.GetStatus( loopchain_pb2.StatusRequest( request="", channel=self.__channel_name, ), conf.GRPC_TIMEOUT_SHORT) else: response = target_peer_stub.call("Status") util.logger.spam('{/api/v1/status/peer} response: ' + response.text) response.block_height = int( json.loads(response.text)["block_height"]) stub.target = target if response.block_height > max_height: # Add peer as higher than this max_height = response.block_height peer_stubs.append(stub) except Exception as e: logging.warning( f"This peer has already been removed from the block height target node. {e}" ) return max_height, peer_stubs
def run_black_peer_server_as_process_and_stub(port, radiostation_port=conf. PORT_RADIOSTATION, group_id=None): process = run_black_peer_server_as_process(port, radiostation_port, group_id) channel = grpc.insecure_channel('localhost:' + str(port)) stub = loopchain_pb2_grpc.PeerServiceStub(channel) return process, stub
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 run_peer_server_as_process_and_stub( port, radiostation_port=conf.PORT_RADIOSTATION, group_id=None, score=None): process = run_peer_server_as_process(port, radiostation_port, group_id, score) channel = grpc.insecure_channel('localhost:' + str(port)) stub = loopchain_pb2_grpc.PeerServiceStub(channel) util.request_server_in_time(stub.GetStatus, loopchain_pb2.StatusRequest(request="")) return process, stub
def menu4_1(params=None): print( "Input Peer Target [IP]:[port] (default '' -> 127.0.0.1:7100, [port] -> 127.0.0.1:[port])" ) choice = input(" >> ") if choice == "": choice = "127.0.0.1:7100" elif choice.find(':') == -1: choice = "127.0.0.1:" + choice print("your input: " + choice) channel = grpc.insecure_channel(choice) peer_stub = loopchain_pb2_grpc.PeerServiceStub(channel) response = peer_stub.GetStatus( loopchain_pb2.StatusRequest(request="hello"), conf.GRPC_TIMEOUT) print("Peer Status: " + str(response)) menu4(peer_stub)
def _get_peer_stub_list(self) -> Tuple[int, int, List[Tuple[str, Any]]]: """It updates peer list for block manager refer to peer list on the loopchain network. This peer list is not same to the peer list of the loopchain network. :return max_height: a height of current blockchain :return unconfirmed_block_height: unconfirmed_block_height on the network :return peer_stubs: current peer list on the network (target, peer_stub) """ max_height = -1 # current max height unconfirmed_block_height = -1 peer_stubs = [] # peer stub list for block height synchronization rs_client: RestClient = self._channel_service.rs_client if not self._channel_service.is_support_node_function( conf.NodeFunction.Vote): status_response = rs_client.call(RestMethod.Status) max_height = status_response['block_height'] peer_stubs.append((rs_client.target, rs_client)) return max_height, unconfirmed_block_height, peer_stubs # Make Peer Stub List [peer_stub, ...] and get max_height of network self._block_height_sync_bad_targets = { k: v for k, v in self._block_height_sync_bad_targets.items() if v > self._blockchain.block_height } utils.logger.info( f"Bad Block Sync Peer : {self._block_height_sync_bad_targets}") peer_target = ChannelProperty().peer_target my_height = self._blockchain.block_height port_pattern = re.compile(r":([0-9]{2,5})$") def _converter(target) -> str: port = int(port_pattern.search(target).group(1)) new_port = f":{port + conf.PORT_DIFF_REST_SERVICE_CONTAINER}" return port_pattern.sub(new_port, target) endpoints = { target: _converter(target) for target in self._block_manager.get_target_list() } for grpc_endpoint, rest_endpoint in endpoints.items(): if grpc_endpoint == peer_target: continue if grpc_endpoint in self._block_height_sync_bad_targets: continue utils.logger.debug( f"try to grpc_endpoint({grpc_endpoint}), rest_endpoint({rest_endpoint})" ) channel = GRPCHelper().create_client_channel(grpc_endpoint) stub = loopchain_pb2_grpc.PeerServiceStub(channel) try: client = RestClient(self._block_manager.channel_name, rest_endpoint) response: dict = client.call(RestMethod.Status, timeout=conf.REST_TIMEOUT) target_block_height = max(response["block_height"], response["unconfirmed_block_height"]) recovery = response.get("recovery", {}) # only recovery_mode node should be included in block sync when running by recovery_mode if conf.RECOVERY_MODE and not recovery.get("mode", False): continue if target_block_height > my_height: peer_stubs.append((grpc_endpoint, stub)) max_height = max(max_height, target_block_height) unconfirmed_block_height = max( unconfirmed_block_height, response["unconfirmed_block_height"]) except Exception as e: utils.logger.warning( f"This peer has already been removed from the block height target node. {e!r}" ) return max_height, unconfirmed_block_height, peer_stubs
def set_stub_port(self, port): self.__stub_to_peer_service = loopchain_pb2_grpc.PeerServiceStub( grpc.insecure_channel(conf.IP_LOCAL + ':' + str(port)))
def block_height_sync(self, target_peer_stub=None): """block height sync with other peers """ if self.__block_height_sync_lock is True: # ***** 이 보정 프로세스는 AnnounceConfirmBlock 메시지를 받았을때 블럭 Height 차이로 Peer 가 처리하지 못한 경우에도 진행한다. # 따라서 이미 sync 가 진행 중일때의 요청은 무시한다. logging.warning("block height sync is already running...") return peer_target = ObjectManager().peer_service.peer_target peer_manager = ObjectManager( ).peer_service.channel_manager.get_peer_manager(self.__channel_name) block_manager = ObjectManager( ).peer_service.channel_manager.get_block_manager(self.__channel_name) self.__block_height_sync_lock = True if target_peer_stub is None: target_peer_stub = peer_manager.get_leader_stub_manager() ### Block Height 보정 작업, Peer의 데이타 동기화 Process ### ### Love&Hate Algorithm ### logging.info("try block height sync...with love&hate") # Make Peer Stub List [peer_stub, ...] and get max_height of network max_height = 0 peer_stubs = [] target_list = list(peer_manager.get_IP_of_peers_in_group()) for peer_target_each in target_list: target = ":".join(peer_target_each.split(":")[1:]) if target != peer_target: logging.debug(f"try to target({target})") channel = grpc.insecure_channel(target) stub = loopchain_pb2_grpc.PeerServiceStub(channel) try: response = stub.GetStatus( loopchain_pb2.StatusRequest( request="", channel=self.__channel_name)) if response.block_height > max_height: # Add peer as higher than this max_height = response.block_height peer_stubs.append(stub) except Exception as e: logging.warning("Already bad.... I don't love you" + str(e)) if len(peer_stubs) == 0: util.logger.warning( f"peer_service:block_height_sync there is no other peer to height sync!" ) self.__block_height_sync_lock = False return my_height = block_manager.get_blockchain().block_height if max_height > my_height: # 자기가 가장 높은 블럭일때 처리 필요 TODO logging.info( f"You need block height sync to: {max_height} yours: {my_height}" ) # 자기(현재 Peer)와 다르면 Peer 목록을 순회하며 마지막 block 에서 자기 Height Block 까지 역순으로 요청한다. # (blockchain 의 block 탐색 로직 때문에 height 순으로 조회는 비효율적이다.) preload_blocks = {} # height : block dictionary # Target Peer 의 마지막 block hash 부터 시작한다. response = target_peer_stub.call( "GetLastBlockHash", loopchain_pb2.StatusRequest(request="", channel=self.__channel_name)) logging.debug(response) request_hash = response.block_hash max_try = max_height - my_height while block_manager.get_blockchain().last_block.block_hash \ != request_hash and max_try > 0: for peer_stub in peer_stubs: response = None try: # 이때 요청 받은 Peer 는 해당 Block 과 함께 자신의 현재 Height 를 같이 보내준다. # TODO target peer 의 마지막 block 보다 높은 Peer 가 있으면 현재 target height 까지 완료 후 # TODO Height Sync 를 다시 한다. response = peer_stub.BlockSync( loopchain_pb2.BlockSyncRequest( block_hash=request_hash, channel=self.__channel_name), conf.GRPC_TIMEOUT) except Exception as e: logging.warning("There is a bad peer, I hate you: " + str(e)) if response is not None and response.response_code == message_code.Response.success: util.logger.spam( f"response block_height({response.block_height})") dump = response.block block = pickle.loads(dump) # 마지막 블럭에서 역순으로 블럭을 구한다. request_hash = block.prev_block_hash # add block to preload_blocks logging.debug("Add preload_blocks Height: " + str(block.height)) preload_blocks[block.height] = block if response.max_block_height > max_height: max_height = response.max_block_height if (my_height + 1) == block.height: max_try = 0 # 더이상 요청을 진행하지 않는다. logging.info("Block Height Sync Complete.") break max_try -= 1 else: # 이 반복 요청중 응답 하지 않은 Peer 는 반복중에 다시 요청하지 않는다. # (TODO: 향후 Bad에 대한 리포트 전략은 별도로 작업한다.) peer_stubs.remove(peer_stub) logging.warning( "Make this peer to bad (error above or no response): " + str(peer_stub)) if preload_blocks.__len__() > 0: while my_height < max_height: add_height = my_height + 1 logging.debug("try add block height: " + str(add_height)) try: block_manager.add_block(preload_blocks[add_height]) my_height = add_height except KeyError as e: logging.error("fail block height sync: " + str(e)) break except exception.BlockError as e: logging.error( "Block Error Clear all block and restart peer.") block_manager.clear_all_blocks() util.exit_and_msg( "Block Error Clear all block and restart peer.") if my_height < max_height: # block height sync 가 완료되지 않았으면 다시 시도한다. logging.warning( "fail block height sync in one time... try again...") self.__block_height_sync_lock = False self.block_height_sync(target_peer_stub) self.__block_height_sync_lock = False
def __get_peer_stub_list(self) -> Tuple[int, int, List[Tuple]]: """It updates peer list for block manager refer to peer list on the loopchain network. This peer list is not same to the peer list of the loopchain network. :return max_height: a height of current blockchain :return unconfirmed_block_height: unconfirmed_block_height on the network :return peer_stubs: current peer list on the network (target, peer_stub) """ max_height = -1 # current max height unconfirmed_block_height = -1 peer_stubs = [] # peer stub list for block height synchronization if not ObjectManager().channel_service.is_support_node_function( conf.NodeFunction.Vote): rs_client = ObjectManager().channel_service.rs_client status_response = rs_client.call(RestMethod.Status) max_height = status_response['block_height'] peer_stubs.append((rs_client.target, rs_client)) return max_height, unconfirmed_block_height, peer_stubs # Make Peer Stub List [peer_stub, ...] and get max_height of network self.__block_height_sync_bad_targets = { k: v for k, v in self.__block_height_sync_bad_targets.items() if v > self.blockchain.block_height } util.logger.info( f"Bad Block Sync Peer : {self.__block_height_sync_bad_targets}") peer_target = ChannelProperty().peer_target my_height = self.blockchain.block_height if self.blockchain.last_block: reps_hash = self.blockchain.get_reps_hash_by_header( self.blockchain.last_block.header) else: reps_hash = ChannelProperty().crep_root_hash rep_targets = self.blockchain.find_preps_targets_by_roothash(reps_hash) target_list = list(rep_targets.values()) for target in target_list: if target == peer_target: continue if target in self.__block_height_sync_bad_targets: continue util.logger.debug(f"try to target({target})") channel = GRPCHelper().create_client_channel(target) stub = loopchain_pb2_grpc.PeerServiceStub(channel) try: response = stub.GetStatus( loopchain_pb2.StatusRequest( request='block_sync', channel=self.__channel_name, ), conf.GRPC_TIMEOUT_SHORT) target_block_height = max(response.block_height, response.unconfirmed_block_height) if target_block_height > my_height: peer_stubs.append((target, stub)) max_height = max(max_height, target_block_height) unconfirmed_block_height = max( unconfirmed_block_height, response.unconfirmed_block_height) except Exception as e: util.logger.warning( f"This peer has already been removed from the block height target node. {e}" ) return max_height, unconfirmed_block_height, peer_stubs
def set_stub_port(self, port, IP_address): self.__stub_to_peer_service = loopchain_pb2_grpc.PeerServiceStub( grpc.insecure_channel(IP_address + ':' + str(port)))