def UnSubscribe(self, request, context): """BlockGenerator 의 broadcast 채널에서 Peer 를 제외한다. :param request: :param context: :return: """ channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel channel_stub = StubCollection().channel_stubs[channel_name] peer_list = [target['peer_target'] for target in self.peer_service.channel_infos[channel_name]["peers"]] if (request.peer_target in peer_list and conf.ENABLE_CHANNEL_AUTH) or \ (request.node_type == loopchain_pb2.CommunityNode and not conf.ENABLE_CHANNEL_AUTH): asyncio.run_coroutine_threadsafe( channel_stub.async_task().remove_audience(peer_target=request.peer_target), self.peer_service.inner_service.loop ) util.logger.spam(f"peer_outer_service::Unsubscribe remove_audience target({request.peer_target}) " f"in channel({request.channel})") else: logging.error(f"This target({request.peer_target}), {request.node_type} failed to unsubscribe.") return loopchain_pb2.CommonReply(response_code=message_code.get_response_code(message_code.Response.fail), message=message_code.get_response_msg("Unknown type peer")) return loopchain_pb2.CommonReply(response_code=message_code.get_response_code(message_code.Response.success), message=message_code.get_response_msg(message_code.Response.success))
def Subscribe(self, request, context): """BlockGenerator 가 broadcast(unconfirmed or confirmed block) 하는 채널에 Peer 를 등록한다. :param request: :param context: :return: """ channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel if not request.peer_id or not request.peer_target: return loopchain_pb2.CommonReply( response_code=message_code.get_response_code(message_code.Response.fail_wrong_subscribe_info), message=message_code.get_response_msg(message_code.Response.fail_wrong_subscribe_info) ) channel_stub = StubCollection().channel_stubs[channel_name] peer_list = [target['peer_target'] for target in self.peer_service.channel_infos[channel_name]["peers"]] if (request.peer_target in peer_list and conf.ENABLE_CHANNEL_AUTH) or \ (request.node_type == loopchain_pb2.CommunityNode and not conf.ENABLE_CHANNEL_AUTH): channel_stub.sync_task().add_audience(peer_target=request.peer_target) util.logger.debug(f"peer_outer_service::Subscribe add_audience " f"target({request.peer_target}) in channel({request.channel}), " f"order({request.peer_order})") else: logging.error(f"This target({request.peer_target}, {request.node_type}) failed to subscribe.") return loopchain_pb2.CommonReply(response_code=message_code.get_response_code(message_code.Response.fail), message=message_code.get_response_msg("Unknown type peer")) return loopchain_pb2.CommonReply(response_code=message_code.get_response_code(message_code.Response.success), message=message_code.get_response_msg(message_code.Response.success))
def VoteUnconfirmedBlock(self, request, context): if self.peer_service.peer_type == loopchain_pb2.PEER: return loopchain_pb2.CommonReply( response_code=message_code.Response.fail_no_leader_peer, message=message_code.get_response_msg(message_code.Response.fail_no_leader_peer)) else: logging.info("Peer vote to : " + request.block_hash + " " + str(request.vote_code)) self.peer_service.block_manager.get_candidate_blocks().vote_to_block( request.block_hash, (False, True)[request.vote_code == message_code.Response.success_validate_block], request.peer_id, request.group_id) return loopchain_pb2.CommonReply(response_code=message_code.Response.success, message="success")
async def AnnounceUnconfirmedBlock(self, request, context): """Send the UnconfirmedBlock includes collected transactions to reps and request to verify it. :param request: :param context: :return: """ channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel channel_stub = StubCollection().channel_stubs[channel_name] try: round_ = request.round_ except AttributeError: round_ = 0 utils.logger.info( f"peer_id({request.peer_id}), height({request.height}), " f"round({round_}), hash({request.hash}), from_recovery({request.from_recovery!r})" ) from_recovery = request.from_recovery if request.from_recovery else False await channel_stub.async_task().announce_unconfirmed_block( request.block, round_, from_recovery) return loopchain_pb2.CommonReply( response_code=message_code.Response.success, message="success")
def AnnounceUnconfirmedBlock(self, request, context): """수집된 tx 로 생성한 Block 을 각 peer 에 전송하여 검증을 요청한다. :param request: :param context: :return: """ unconfirmed_block = pickle.loads(request.block) logging.debug( f"#block \n" f"peer_id({unconfirmed_block.peer_id})\n" f"made_block_count({unconfirmed_block.made_block_count})\n" f"is_voting_block({unconfirmed_block.is_voting_block})\n" f"is_divided_block({unconfirmed_block.is_divided_block})") self.peer_service.block_manager.add_unconfirmed_block( unconfirmed_block) if unconfirmed_block.made_block_count >= conf.LEADER_BLOCK_CREATION_LIMIT \ and unconfirmed_block.is_voting_block is True \ and unconfirmed_block.is_divided_block is False: self.peer_service.reset_leader(unconfirmed_block.next_leader_peer) return loopchain_pb2.CommonReply( response_code=message_code.Response.success, message="success")
def Echo(self, request, context): """gRPC 기본 성능을 확인하기 위한 echo interface, loopchain 기능과는 무관하다. :return: request 를 message 되돌려 준다. """ return loopchain_pb2.CommonReply(response_code=message_code.Response.success, message=request.request)
def AnnounceUnconfirmedBlock(self, request, context): """수집된 tx 로 생성한 Block 을 각 peer 에 전송하여 검증을 요청한다. :param request: :param context: :return: """ # self.__block_manager.add_unconfirmed_block(request.block) unconfirmed_block = pickle.loads(request.block) logging.warning("Black Peer makes Fail validate Message by intention!") vote_code, message = message_code.get_response( message_code.Response.fail_validate_block) self.peer_service.stub_to_blockgenerator.call( "VoteUnconfirmedBlock", loopchain_pb2.BlockVote( vote_code=vote_code, message=message, block_hash=unconfirmed_block.block_hash, peer_id=ObjectManager().peer_service.peer_id, group_id=ObjectManager().peer_service.group_id)) return loopchain_pb2.CommonReply( response_code=message_code.Response.success, message="success")
def AnnounceConfirmedBlock(self, request, context): """Block Generator 가 announce 하는 인증된 블록의 대한 hash 를 전달받는다. :param request: BlockAnnounce of loopchain.proto :param context: gRPC parameter :return: CommonReply of loopchain.proto """ # Peer To BlockGenerator logging.debug("AnnounceConfirmedBlock block hash: " + request.block_hash) response_code, response_msg = message_code.get_response( message_code.Response.fail_announce_block) confirmed_block = pickle.loads(request.block) logging.debug(f"block \n" f"peer_id({confirmed_block.peer_id})\n" f"made_block_count({confirmed_block.made_block_count})\n" f"is_divided_block({confirmed_block.is_divided_block})") if len(request.block) > 0: logging.warning( "AnnounceConfirmedBlock without Consensus ====================" ) # 아래의 return 값을 확인하지 않아도 예외인 경우 아래 except 에서 확인된다. self.peer_service.add_unconfirm_block(request.block) try: self.peer_service.block_manager.confirm_block(request.block_hash) response_code, response_msg = message_code.get_response( message_code.Response.success_announce_block) except (BlockchainError, BlockInValidError, BlockError) as e: logging.error("AnnounceConfirmedBlock: " + str(e)) return loopchain_pb2.CommonReply(response_code=response_code, message=response_msg)
def AnnounceDeletePeer(self, request, context): logging.debug( f"AnnounceDeletePeer peer_id({request.peer_id}) group_id({request.group_id})" ) self.peer_service.peer_list.remove_peer(request.peer_id, request.group_id) return loopchain_pb2.CommonReply(response_code=0, message="success")
def AnnounceNewPeer(self, request, context): """RadioStation에서 Broadcasting 으로 신규피어목록을 받아온다 :param request: PeerRequest :param context: :return: """ # RadioStation To Peer logging.info('Here Comes new peer: ' + str(request)) if len(request.peer_object) > 0: peer = pickle.loads(request.peer_object) # 서버로부터 발급된 토큰 검증 # Secure 인 경우 검증에 통과하여야만 peer_list에 추가함 if self.peer_service.auth.is_secure\ and self.peer_service.auth.verify_new_peer(peer, loopchain_pb2.PEER) is False: # TODO AnnounceNewPeer 과정을 실패로 처리한다. logging.debug("New Peer Validation Fail") else: logging.debug("Add New Peer: " + str(peer.peer_id)) self.peer_service.peer_list.add_peer_object(peer) logging.debug("Try save peer list...") self.peer_service.common_service.save_peer_list( self.peer_service.peer_list) self.peer_service.show_peers() return loopchain_pb2.CommonReply(response_code=0, message="success")
async def VoteUnconfirmedBlock(self, request, context): channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel utils.logger.info(f"vote({request.vote})") channel_stub = StubCollection().channel_stubs[channel_name] await channel_stub.async_task().vote_unconfirmed_block(request.vote) return loopchain_pb2.CommonReply( response_code=message_code.Response.success, message="success")
def ComplainLeader(self, request, context): logging.debug("ComplainLeader: " + request.message) # TODO AnnounceComplained 메시지를 브로드 캐스트 하여 ComplainLeader 에 대한 투표를 받는다. # 수집후 AnnounceNewLeader 메시지에 ComplainLeader 투표 결과를 담아서 발송한다. # 현재 우선 AnnounceNewLeader 를 즉시 전송하게 구현한다. Leader Change 를 우선 확인하기 위한 임시 구현 self.peer_service.peer_list.announce_new_leader(request.complained_leader_id, request.new_leader_id) return loopchain_pb2.CommonReply(response_code=message_code.Response.success, message="success")
def UnSubscribe(self, request, context): """BlockGenerator 의 broadcast 채널에서 Peer 를 제외한다. :param request: :param context: :return: """ self.peer_service.common_service.remove_audience(request.peer_id, request.peer_target) return loopchain_pb2.CommonReply(response_code=0, message="success")
def AnnounceNewLeader(self, request, context): if not request.channel: raise Exception("peer_outer_service:AnnounceNewLeader : Channel is not defined.") logging.debug(f"AnnounceNewLeader({request.channel}): " + request.message) channel_stub = StubCollection().channel_stubs[request.channel] channel_stub.sync_task().reset_leader(request.new_leader_id) return loopchain_pb2.CommonReply(response_code=message_code.Response.success, message="success")
def VoteUnconfirmedBlock(self, request, context): channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel utils.logger.debug(f"VoteUnconfirmedBlock vote({request.vote})") channel_stub = StubCollection().channel_stubs[channel_name] asyncio.run_coroutine_threadsafe( channel_stub.async_task().vote_unconfirmed_block(request.vote), self.peer_service.inner_service.loop ) return loopchain_pb2.CommonReply(response_code=message_code.Response.success, message="success")
def Subscribe(self, request, context): """BlockGenerator 가 broadcast(unconfirmed or confirmed block) 하는 채널에 Peer 를 등록한다. :param request: :param context: :return: """ self.peer_service.common_service.add_audience(request) return loopchain_pb2.CommonReply(response_code=message_code.get_response_code(message_code.Response.success), message=message_code.get_response_msg(message_code.Response.success))
def ComplainLeader(self, request: ComplainLeaderRequest, context): channel = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel utils.logger.info(f"ComplainLeader {request.complain_vote}") channel_stub = StubCollection().channel_stubs[channel] asyncio.run_coroutine_threadsafe( channel_stub.async_task().complain_leader(vote_dumped=request.complain_vote), self.peer_service.inner_service.loop ) return loopchain_pb2.CommonReply(response_code=message_code.Response.success, message="success")
def AddTxList(self, request: loopchain_pb2.TxSendList, context): """Add tx to Block Manager :param request: :param context: :return: """ utils.logger.spam(f"peer_outer_service:AddTxList try validate_dumped_tx_message") channel_name = request.channel or conf.LOOPCHAIN_DEFAULT_CHANNEL StubCollection().channel_tx_receiver_stubs[channel_name].sync_task().add_tx_list(request) return loopchain_pb2.CommonReply(response_code=message_code.Response.success, message="success")
def AnnounceUnconfirmedBlock(self, request, context): """수집된 tx 로 생성한 Block 을 각 peer 에 전송하여 검증을 요청한다. :param request: :param context: :return: """ unconfirmed_block = pickle.loads(request.block) self.peer_service.block_manager.add_unconfirmed_block(unconfirmed_block) return loopchain_pb2.CommonReply(response_code=message_code.Response.success, message="success")
def AddTx(self, request, context): """피어로부터 받은 tx 를 Block Manager 에 추가한다. 이 기능은 Block Generator 에서만 동작해야 한다. 일반 Peer 는 이 기능을 사용할 권한을 가져서는 안된다. :param request: :param context: :return: """ if self.peer_service.peer_type == loopchain_pb2.PEER: return loopchain_pb2.CommonReply( response_code=message_code.Response.fail_no_leader_peer, message=message_code.get_response_msg(message_code.Response.fail_no_leader_peer)) else: # Block Manager 에 tx 추가 if self.peer_service.block_manager.consensus.block is None: return loopchain_pb2.CommonReply( response_code=message_code.Response.fail_made_block_count_limited, message="this leader can't make more block") self.peer_service.block_manager.add_tx_unloaded(request.tx) return loopchain_pb2.CommonReply(response_code=message_code.Response.success, message="success")
def AnnounceUnconfirmedBlock(self, request, context): """수집된 tx 로 생성한 Block 을 각 peer 에 전송하여 검증을 요청한다. :param request: :param context: :return: """ channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel util.logger.debug(f"peer_outer_service::AnnounceUnconfirmedBlock channel({channel_name})") channel_stub = StubCollection().channel_stubs[channel_name] channel_stub.sync_task().announce_unconfirmed_block(request.block) return loopchain_pb2.CommonReply(response_code=message_code.Response.success, message="success")
def VoteUnconfirmedBlock(self, request, context): channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel util.logger.debug(f"VoteUnconfirmedBlock block_hash({request.block_hash})") channel_stub = StubCollection().channel_stubs[channel_name] channel_stub.sync_task().vote_unconfirmed_block( peer_id=request.peer_id, group_id=request.group_id, block_hash=request.block_hash, vote_code=request.vote_code) return loopchain_pb2.CommonReply(response_code=message_code.Response.success, message="success")
async def ComplainLeader(self, request: ComplainLeaderRequest, context): channel = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel utils.logger.info( f"complain_vote: {request.complain_vote}, from_recovery({request.from_recovery!r})" ) from_recovery = request.from_recovery if request.from_recovery else False channel_stub = StubCollection().channel_stubs[channel] await channel_stub.async_task().complain_leader( vote_dumped=request.complain_vote, from_recovery=from_recovery) return loopchain_pb2.CommonReply( response_code=message_code.Response.success, message="success")
async def AddTxList(self, request: loopchain_pb2.TxSendList, context): """Add tx to Block Manager :param request: :param context: :return: """ utils.logger.info(f"length of txlist: {len(request.tx_list)}") channel_name = request.channel or conf.LOOPCHAIN_DEFAULT_CHANNEL tx_receiver_stub = StubCollection( ).channel_tx_receiver_stubs[channel_name] await tx_receiver_stub.async_task().add_tx_list(request) return loopchain_pb2.CommonReply( response_code=message_code.Response.success, message="success")
def AnnounceDeletePeer(self, request, context): """delete peer by radio station heartbeat, It delete peer info over whole channels. :param request: :param context: :return: """ channel = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel logging.debug(f"AnnounceDeletePeer peer_id({request.peer_id}) group_id({request.group_id})") if self.peer_service.peer_id != request.peer_id: channel_stub = StubCollection().channel_stubs[channel] channel_stub.sync_task().delete_peer(request.peer_id, request.group_id) return loopchain_pb2.CommonReply(response_code=0, message="success")
def ComplainLeader(self, request: ComplainLeaderRequest, context): channel = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel util.logger.notice(f"ComplainLeader " f"height({request.block_height}) complained_peer({request.complained_leader_id})") channel_stub = StubCollection().channel_stubs[channel] channel_stub.sync_task().complain_leader( complained_leader_id=request.complained_leader_id, new_leader_id=request.new_leader_id, block_height=request.block_height, peer_id=request.peer_id, group_id=request.group_id ) return loopchain_pb2.CommonReply(response_code=message_code.Response.success, message="success")
def AnnounceNewPeer(self, request, context): """RadioStation에서 Broadcasting 으로 신규 피어정보를 받아온다 :param request: PeerRequest :param context: :return: """ # RadioStation To Peer # prevent to show certificate content # logging.info('Here Comes new peer: ' + str(request)) channel = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel logging.debug(f"peer outer service::AnnounceNewPeer channel({channel})") if request.peer_object: channel_stub = StubCollection().channel_stubs[channel] channel_stub.sync_task().announce_new_peer(request.peer_object, request.peer_target) return loopchain_pb2.CommonReply(response_code=0, message="success")
def AnnounceUnconfirmedBlock(self, request, context): """Send the UnconfirmedBlock includes collected transactions to reps and request to verify it. :param request: :param context: :return: """ channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel channel_stub = StubCollection().channel_stubs[channel_name] try: round_ = request.round_ except AttributeError: round_ = 0 asyncio.run_coroutine_threadsafe( channel_stub.async_task().announce_unconfirmed_block(request.block, round_), self.peer_service.inner_service.loop ) return loopchain_pb2.CommonReply(response_code=message_code.Response.success, message="success")
def NotifyProcessError(self, request, context): """Peer Stop by Process Error """ util.exit_and_msg(request.request) return loopchain_pb2.CommonReply(response_code=message_code.Response.success, message="success")
def AnnounceNewLeader(self, request, context): logging.debug("AnnounceNewLeader: " + request.message) self.peer_service.reset_leader(request.new_leader_id) return loopchain_pb2.CommonReply( response_code=message_code.Response.success, message="success")