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 ready(self, amqp_target, amqp_key): StubCollection().amqp_target = amqp_target StubCollection().amqp_key = amqp_key async def ready_tasks(): from loopchain import loggers loggers.get_preset().update_logger() loggers.update_other_loggers() logging.debug('rest_server:initialize') await StubCollection().create_peer_stub() channels_info = await StubCollection().peer_stub.async_task( ).get_channel_infos() channel_name = None for channel_name, channel_info in channels_info.items(): await StubCollection().create_channel_stub(channel_name) await StubCollection().create_icon_score_stub(channel_name) results = await StubCollection().peer_stub.async_task( ).get_channel_info_detail(channel_name) RestProperty().node_type = conf.NodeType(results[6]) RestProperty().rs_target = results[3] logging.debug( f'rest_server:initialize complete. ' f'node_type({RestProperty().node_type}), rs_target({RestProperty().rs_target})' ) self.__app.add_task(ready_tasks())
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 request_rollback(self) -> bool: """Request block data rollback behind to 1 block :return: if rollback success return True, else return False """ target_block = self.blockchain.find_block_by_hash32(self.blockchain.last_block.header.prev_hash) if not self.blockchain.check_rollback_possible(target_block): util.logger.warning(f"The request cannot be rollback to the target block({target_block}).") return False request_origin = { 'blockHeight': target_block.header.height, 'blockHash': target_block.header.hash.hex_0x() } request = convert_params(request_origin, ParamType.roll_back) stub = StubCollection().icon_score_stubs[ChannelProperty().name] util.logger.debug(f"Rollback request({request})") response: dict = cast(dict, stub.sync_task().rollback(request)) try: response_to_json_query(response) except GenericJsonRpcServerError as e: util.logger.warning(f"response error = {e}") else: result_height = response.get("blockHeight") if hex(target_block.header.height) == result_height: util.logger.info(f"Rollback Success. result height = {result_height}") self.blockchain.rollback(target_block) self.rebuild_block() return True util.logger.warning(f"Rollback Fail. response = {response}") return False
def __init__(self, channel, score_package, amqp_target, amqp_key): """Score service init """ loggers.get_preset().channel_name = channel loggers.get_preset().score_package = score_package loggers.get_preset().update_logger() loggers.update_other_loggers() self.score: PeerScore = None self.score_plugin = Plugins().load_score_plugin(channel) self.iiss_plugin = Plugins().load_iiss_plugin(channel) self.__peer_id: str = None self.__channel_name: str = channel StubCollection().amqp_key = amqp_key StubCollection().amqp_target = amqp_target score_queue_name = conf.SCORE_QUEUE_NAME_FORMAT.format( score_package_name=score_package, channel_name=channel, amqp_key=amqp_key) self.__inner_service = ScoreInnerService(amqp_target, score_queue_name, conf.AMQP_USERNAME, conf.AMQP_PASSWORD, score_service=self) setproctitle.setproctitle(f"{setproctitle.getproctitle()} {channel}")
def score_invoke(self, _block: Block) -> dict or None: method = "icx_sendTransaction" transactions = [] for tx in _block.body.transactions.values(): tx_serializer = TransactionSerializer.new(tx.version, self.block_manager.get_blockchain().tx_versioner) transaction = { "method": method, "params": tx_serializer.to_full_data(tx) } transactions.append(transaction) request = { 'block': { 'blockHeight': _block.header.height, 'blockHash': _block.header.hash.hex(), 'prevBlockHash': _block.header.prev_hash.hex() if _block.header.prev_hash else '', 'timestamp': _block.header.timestamp }, 'transactions': transactions } request = convert_params(request, ParamType.invoke) stub = StubCollection().icon_score_stubs[ChannelProperty().name] response = stub.sync_task().invoke(request) response_to_json_query(response) block_builder = BlockBuilder.from_new(_block, self.__block_manager.get_blockchain().tx_versioner) block_builder.commit_state = { ChannelProperty().name: response['stateRootHash'] } new_block = block_builder.build() return new_block, response["txResults"]
def score_change_block_hash(self, block_height, old_block_hash, new_block_hash): change_hash_info = json.dumps({"block_height": block_height, "old_block_hash": old_block_hash, "new_block_hash": new_block_hash}) if not util.channel_use_icx(ChannelProperty().name): stub = StubCollection().score_stubs[ChannelProperty().name] stub.sync_task().change_block_hash(change_hash_info)
def GetBlock(self, request, context): """Block 정보를 조회한다. :param request: loopchain.proto 의 GetBlockRequest 참고 request.block_hash: 조회할 block 의 hash 값, "" 로 조회하면 마지막 block 의 hash 값을 리턴한다. request.block_data_filter: block 정보 중 조회하고 싶은 key 값 목록 "key1, key2, key3" 형식의 string request.tx_data_filter: block 에 포함된 transaction(tx) 중 조회하고 싶은 key 값 목록 "key1, key2, key3" 형식의 string :param context: :return: loopchain.proto 의 GetBlockReply 참고, block_hash, block 정보 json, block 에 포함된 tx 정보의 json 리스트를 받는다. 포함되는 정보는 param 의 filter 에 따른다. """ channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel channel_stub = StubCollection().channel_stubs[channel_name] response_code, block_hash, confirm_info, block_data_json, tx_data_json_list = \ channel_stub.sync_task().get_block( block_height=request.block_height, block_hash=request.block_hash, block_data_filter=request.block_data_filter, tx_data_filter=request.tx_data_filter) return loopchain_pb2.GetBlockReply(response_code=response_code, block_hash=block_hash, block_data_json=block_data_json, confirm_info=confirm_info, tx_data_json=tx_data_json_list)
def __request_roll_back(self): target_block = self.blockchain.find_block_by_hash32( self.blockchain.last_block.header.prev_hash) if not self.blockchain.check_rollback_possible(target_block): util.logger.warning( f"The request cannot be rolled back to the target block({target_block})." ) return request_origin = { 'blockHeight': target_block.header.height, 'blockHash': target_block.header.hash.hex_0x() } request = convert_params(request_origin, ParamType.roll_back) stub = StubCollection().icon_score_stubs[ChannelProperty().name] util.logger.debug(f"Rollback request({request})") response: dict = cast(dict, stub.sync_task().rollback(request)) response_to_json_query(response) result_height = response.get("blockHeight") if hex(target_block.header.height) == result_height: util.logger.info(f"Rollback Success") self.blockchain.roll_back(target_block) self.rebuild_block() else: util.logger.warning(f"{response}")
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 GetTx(self, request, context): """get transaction :param request: tx_hash :param context:channel_loopchain_default :return: """ channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel channel_stub = StubCollection().channel_stubs[channel_name] tx = channel_stub.sync_task().get_tx(request.tx_hash) response_code, response_msg = message_code.get_response( message_code.Response.fail) response_meta = "" response_data = "" response_sign = b'' response_public_key = b'' if tx is not None: response_code, response_msg = message_code.get_response( message_code.Response.success) response_meta = json.dumps(tx.meta) response_data = tx.get_data().decode(conf.PEER_DATA_ENCODING) response_sign = tx.signature response_public_key = tx.public_key return loopchain_pb2.GetTxReply(response_code=response_code, meta=response_meta, data=response_data, signature=response_sign, public_key=response_public_key, more_info=response_msg)
async def _run(): route_key = conf.PEER_QUEUE_NAME_FORMAT.format( amqp_key=conf.AMQP_KEY) peer_inner_service = PeerInnerService(conf.AMQP_TARGET, route_key, peer_service=None) peer_inner_service._callback_connection_lost_callback = lambda conn: None await peer_inner_service.connect() route_key = conf.CHANNEL_QUEUE_NAME_FORMAT.format( channel_name=conf.LOOPCHAIN_DEFAULT_CHANNEL, amqp_key=conf.AMQP_KEY) channel_inner_service = ChannelInnerService(conf.AMQP_TARGET, route_key, channel_service=None) channel_inner_service._callback_connection_lost_callback = lambda conn: None await channel_inner_service.connect() StubCollection().amqp_target = conf.AMQP_TARGET StubCollection().amqp_key = conf.AMQP_KEY await StubCollection().create_peer_stub() result = await StubCollection().peer_stub.async_task().hello() self.assertEqual(result, 'peer_hello') await StubCollection().create_channel_stub( conf.LOOPCHAIN_DEFAULT_CHANNEL) result = await StubCollection().channel_stubs[ conf.LOOPCHAIN_DEFAULT_CHANNEL].async_task().hello() self.assertEqual(result, 'channel_hello') await peer_inner_service._connection.close() await channel_inner_service._connection.close()
async def icx_sendTransaction(**kwargs): if RestProperty().node_type == conf.NodeType.CitizenNode: return await redirect_request_to_rs( kwargs, RestProperty().rs_target) request = make_request("icx_sendTransaction", kwargs) icon_stub = StubCollection().icon_score_stubs[conf.LOOPCHAIN_DEFAULT_CHANNEL] response = await icon_stub.async_task().validate_transaction(request) response_to_json_query(response) channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL channel_stub = StubCollection().channel_stubs[channel_name] response_code, tx_hash = \ await channel_stub.async_task().create_icx_tx(kwargs) if response_code != message_code.Response.success: raise GenericJsonRpcServerError( code=JsonError.INVALID_REQUEST, message=message_code.responseCodeMap[response_code][1], http_status=status.HTTP_BAD_REQUEST ) if tx_hash is None: raise GenericJsonRpcServerError( code=JsonError.INVALID_REQUEST, message='txHash is None', http_status=status.HTTP_BAD_REQUEST ) return convert_params(tx_hash, ParamType.send_tx_response)
def score_write_precommit_state(self, block: Block): logging.debug( f"call score commit {ChannelProperty().name} {block.header.height} {block.header.hash.hex()}" ) new_block_hash = block.header.hash try: old_block_hash = self.__block_manager.get_old_block_hash( block.header.height, new_block_hash) except KeyError: old_block_hash = new_block_hash logging.debug(f"Block Hash : {old_block_hash} -> {new_block_hash}") request = { "blockHeight": block.header.height, "oldBlockHash": old_block_hash.hex(), "newBlockHash": new_block_hash.hex() } request = convert_params(request, ParamType.write_precommit_state) stub = StubCollection().icon_score_stubs[ChannelProperty().name] precommit_result: dict = stub.sync_task().write_precommit_state( request) if "error" in precommit_result: raise WritePrecommitStateError(precommit_result['error']) self.__block_manager.pop_old_block_hashes(block.header.height) return True
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 AnnounceNewBlockForVote(self, request, context): """수집된 tx 로 생성한 Block 을 각 peer 에 전송하여 검증을 요청한다. :param request: :param context: :return: """ channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel logging.debug( f"peer_outer_service::AnnounceNewBlockForVote channel({channel_name})" ) block: Block = pickle.loads(request.block) epoch = pickle.loads(request.epoch) logging.debug(f"#block \n" f"epoch({epoch.block_height})\n" f"prev_epoch({epoch.prev_epoch})\n" f"block_type({block.block_type})\n" f"block_hash({block.block_hash})\n" f"peer_id({block.peer_id})\n" f"made_block_count({block.made_block_count})\n" f"block_type({block.block_type})\n") channel_stub = StubCollection().channel_stubs[channel_name] channel_stub.sync_task().announce_new_block_for_vote(block, epoch) return loopchain_pb2.CommonReply( response_code=message_code.Response.success, message="success")
def genesis_invoke(self, block: Block) -> ('Block', dict): method = "icx_sendTransaction" transactions = [] for tx in block.body.transactions.values(): hash_version = conf.CHANNEL_OPTION[ ChannelProperty().name]["genesis_tx_hash_version"] tx_serializer = TransactionSerializer.new(tx.version, hash_version) transaction = { "method": method, "params": { "txHash": tx.hash.hex() }, "genesisData": tx_serializer.to_full_data(tx) } transactions.append(transaction) request = { 'block': { 'blockHeight': block.header.height, 'blockHash': block.header.hash.hex(), 'timestamp': block.header.timestamp }, 'transactions': transactions } request = convert_params(request, ParamType.invoke) stub = StubCollection().icon_score_stubs[ChannelProperty().name] response = stub.sync_task().invoke(request) response_to_json_query(response) block_builder = BlockBuilder.from_new(block) block_builder.commit_state = { ChannelProperty().name: response['stateRootHash'] } new_block = block_builder.build() return new_block, response["txResults"]
async def icx_sendTransaction(**kwargs): if RestProperty().node_type == conf.NodeType.CitizenNode: return await redirect_request_to_rs(kwargs, RestProperty().rs_target, conf.ApiVersion.v2.name) request = make_request("icx_sendTransaction", kwargs, ParamType.send_tx) icon_stub = StubCollection().icon_score_stubs[ conf.LOOPCHAIN_DEFAULT_CHANNEL] response = await icon_stub.async_task().validate_transaction(request) response_to_json_query(response) channel_inner_tasks = StubCollection().channel_stubs[ conf.LOOPCHAIN_DEFAULT_CHANNEL] code, tx_hash = await channel_inner_tasks.async_task().create_icx_tx( kwargs) response_data = {'response_code': code} if code != message_code.Response.success: response_data['message'] = message_code.responseCodeMap[code][1] else: response_data['tx_hash'] = tx_hash util.logger.spam(f"response_data: ({response_data})") return response_data
def __init__(self, tx_versioner: TransactionVersioner, add_tx_list_callback, loop, crash_callback_in_join_thread): super().__init__() self.__is_running = True self.__tx_queue = self.Queue() self.__tx_queue.cancel_join_thread() async def _add_tx_list(tx_list): add_tx_list_callback(tx_list) def _receive_tx_list(tx_queue): while True: tx_list = tx_queue.get() if not self.__is_running or tx_list is None: break asyncio.run_coroutine_threadsafe(_add_tx_list(tx_list), loop) while not tx_queue.empty(): tx_queue.get() self.__receive_thread = threading.Thread(target=_receive_tx_list, args=(self.__tx_queue,)) self.__receive_thread.start() args = (ChannelProperty().name, StubCollection().amqp_target, StubCollection().amqp_key, tx_versioner, self.__tx_queue) super().start(target=ChannelTxReceiverInnerService.main, args=args, crash_callback_in_join_thread=crash_callback_in_join_thread)
def __init__(self, channel_name, amqp_target, amqp_key): self.__block_manager: BlockManager = None self.__score_container: CommonSubprocess = None self.__score_info: dict = None self.__peer_auth: PeerAuthorization = None self.__peer_manager: PeerManager = None self.__broadcast_scheduler: BroadcastScheduler = None self.__radio_station_stub = None self.__consensus: Consensus = None self.__proposer: Proposer = None self.__acceptor: Acceptor = None self.__timer_service = TimerService() loggers.get_preset().channel_name = channel_name loggers.get_preset().update_logger() channel_queue_name = conf.CHANNEL_QUEUE_NAME_FORMAT.format(channel_name=channel_name, amqp_key=amqp_key) self.__inner_service = ChannelInnerService( amqp_target, channel_queue_name, conf.AMQP_USERNAME, conf.AMQP_PASSWORD, channel_service=self) logging.info(f"ChannelService : {channel_name}, Queue : {channel_queue_name}") ChannelProperty().name = channel_name ChannelProperty().amqp_target = amqp_target StubCollection().amqp_key = amqp_key StubCollection().amqp_target = amqp_target command_arguments.add_raw_command(command_arguments.Type.Channel, channel_name) command_arguments.add_raw_command(command_arguments.Type.AMQPTarget, amqp_target) command_arguments.add_raw_command(command_arguments.Type.AMQPKey, amqp_key) ObjectManager().channel_service = self
def __prevent_next_block_mismatch(self, next_block: Block) -> bool: logging.debug(f"prevent_block_mismatch...") score_stub = StubCollection().icon_score_stubs[self.__channel_name] request = { "method": "ise_getStatus", "params": { "filter": ["lastBlock"] } } response = score_stub.sync_task().query(request) score_last_block_height = int(response['lastBlock']['blockHeight'], 16) if score_last_block_height == next_block.header.height: logging.debug(f"already invoked block in score...") return False if score_last_block_height < next_block.header.height: for invoke_block_height in range(score_last_block_height + 1, next_block.header.height): logging.debug( f"mismatch invoke_block_height({invoke_block_height}) " f"score_last_block_height({score_last_block_height}) " f"next_block_height({next_block.header.height})") invoke_block = self.find_block_by_height(invoke_block_height) if invoke_block is None: raise RuntimeError( "Error raised during prevent mismatch block, " f"Cannot find block({invoke_block_height}") invoke_block, invoke_block_result = ObjectManager( ).channel_service.score_invoke(invoke_block) self.__add_tx_to_block_db(invoke_block, invoke_block_result) ObjectManager().channel_service.score_write_precommit_state( invoke_block) return True if score_last_block_height == next_block.header.height + 1: try: invoke_result_block_height_bytes = \ self.__confirmed_block_db.Get(BlockChain.INVOKE_RESULT_BLOCK_HEIGHT_KEY) invoke_result_block_height = int.from_bytes( invoke_result_block_height_bytes, byteorder='big') if invoke_result_block_height == next_block.header.height: logging.debug(f"already saved invoke result...") return False except KeyError: logging.debug(f"There is no invoke result height in db.") else: util.exit_and_msg( "Too many different(over 2) of block height between the loopchain and score. " "Peer will be down. : " f"loopchain({next_block.header.height})/score({score_last_block_height})" ) return True
def Query(self, request, context): """Score 의 invoke 로 생성된 data 에 대한 query 를 수행한다.""" channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel score_stub = StubCollection().score_stubs[channel_name] response_code, response = score_stub.sync_task().query(request.params) return loopchain_pb2.QueryReply(response_code=response_code, response=response)
def score_remove_precommit_state(self, block: Block): invoke_fail_info = json.dumps({ "block_height": block.height, "block_hash": block.block_hash }) stub = StubCollection().score_stubs[ChannelProperty().name] stub.sync_task().remove_precommit_state(invoke_fail_info) return True
async def _wait(): StubCollection().amqp_target = conf.AMQP_TARGET StubCollection().amqp_key = f"{util.get_private_ip()}:{port}" logging.debug(f'{StubCollection().amqp_key} peer hello') await StubCollection().create_peer_stub() await StubCollection().peer_stub.async_task().hello() logging.debug(f'{StubCollection().amqp_key} peer hello complete')
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 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")
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 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 score_change_block_hash(self, block_height, old_block_hash, new_block_hash): change_hash_info = json.dumps({ "block_height": block_height, "old_block_hash": old_block_hash, "new_block_hash": new_block_hash }) if not conf.USE_EXTERNAL_SCORE: stub = StubCollection().score_stubs[ChannelProperty().name] stub.sync_task().change_block_hash(change_hash_info)
def __handler_peer_list(self, request, context): channel_name = conf.LOOPCHAIN_DEFAULT_CHANNEL if request.channel == '' else request.channel channel_stub = StubCollection().channel_stubs[channel_name] all_group_peer_list_str, peer_list_str = channel_stub.sync_task().get_peer_list() message = "All Group Peers count: " + all_group_peer_list_str return loopchain_pb2.Message( code=message_code.Response.success, message=message, meta=peer_list_str)