async def __run_score_container(self): if not conf.USE_EXTERNAL_SCORE or conf.EXTERNAL_SCORE_RUN_IN_LAUNCHER: process_args = [ 'python3', '-m', 'loopchain', 'score', '--channel', ChannelProperty().name, '--score_package', ChannelProperty().score_package ] process_args += command_arguments.get_raw_commands_by_filter( command_arguments.Type.AMQPTarget, command_arguments.Type.AMQPKey, command_arguments.Type.Develop, command_arguments.Type.ConfigurationFilePath) self.__score_container = CommonSubprocess(process_args) if util.channel_use_icx(ChannelProperty().name): await StubCollection().create_icon_score_stub( ChannelProperty().name) await StubCollection().icon_score_stubs[ChannelProperty().name ].connect() await StubCollection().icon_score_stubs[ChannelProperty().name ].async_task().hello() return None else: await StubCollection().create_score_stub( ChannelProperty().name, ChannelProperty().score_package) await StubCollection().score_stubs[ChannelProperty().name ].connect() await StubCollection().score_stubs[ChannelProperty().name ].async_task().hello() return await self.__load_score()
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 verify_through_score_invoke(self, is_leader: bool=False): # Block에 속한 tx목록을 순회하면서 Invoke 실행 is_verified = True invoke_results = {} if ObjectManager().channel_service is None: # all results to success success_result = dict(code=int(message_code.Response.success)) invoke_results = util.create_invoke_result_specific_case(self.confirmed_transaction_list, success_result) else: try: origin_commit_state = copy.deepcopy(self.commit_state) invoke_results = ObjectManager().channel_service.score_invoke(self) if is_leader: # set commit state as a leader while do nothing, block commit_state set by score_invoke util.logger.spam(f"verify_through_score_invoke commit_state({self.commit_state})") else: # verify commit state with leader's(origin_commit_state) # this block must have leader's commit state if origin_commit_state != self.commit_state: logging.warning(f"block:verify_through_score_invoke fail commit state integrity!!") is_verified = False else: util.logger.spam(f"verify_through_score_invoke commit state verified.") # peer have to restore origin_commit_state. # And when receive block confirm message check again origin and peer's commit state. self.commit_state = copy.deepcopy(origin_commit_state) except Exception as e: # When Grpc Connection Raise Exception # save all result{'code': ScoreResponse.SCORE_CONTAINER_EXCEPTION, 'message': str(e)} logging.error(f'This error occurred while Score_invoke has failed in verify block : {e}') invoke_results = {} # util.logger.spam(f'Block::verify_through_score_invoke >>>>> invoke_results :: {invoke_results}') need_rebuild = False if not util.channel_use_icx(self.__channel_name): fail_list = [tx_hash for tx_hash, invoke_result in invoke_results.items() if invoke_result["code"] != message_code.Response.success] need_rebuild = len(fail_list) > 0 if is_leader: if need_rebuild: for tx_hash in fail_list: tx = self.find_tx_by_hash(tx_hash) self.confirmed_transaction_list.discard(tx) is_verified = self.confirmed_tx_len > 0 elif conf.ALLOW_MAKE_EMPTY_BLOCK and not need_rebuild: is_verified = True else: is_verified = not need_rebuild return is_verified, need_rebuild, invoke_results
def __init_peer_auth(self): try: channel_authorization = IcxAuthorization if util.channel_use_icx(ChannelProperty().name) \ else PeerAuthorization self.__peer_auth = channel_authorization(ChannelProperty().name) except Exception as e: logging.exception(f"peer auth init fail cause : {e}") util.exit_and_msg(f"peer auth init fail cause : {e}")
def score_remove_precommit_state(self, block: Block): if not util.channel_use_icx(ChannelProperty().name): request = { "blockHeight": block.height, "blockHash": block.block_hash, } request = convert_params(request, ParamType.remove_precommit_state) stub = StubCollection().icon_score_stubs[ChannelProperty().name] stub.sync_task().remove_precommit_state(request) return True else: 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
def start_as_score(args): # apply default configure values channel = args.channel or conf.LOOPCHAIN_DEFAULT_CHANNEL score_package = args.score_package or conf.DEFAULT_SCORE_PACKAGE amqp_target = args.amqp_target or conf.AMQP_TARGET amqp_key = args.amqp_key or conf.AMQP_KEY if util.channel_use_icx(channel) and conf.USE_EXTERNAL_SCORE: if conf.EXTERNAL_SCORE_RUN_IN_LAUNCHER: from iconservice.icon_service import IconService from iconservice.icon_config import default_icon_config from iconcommons.icon_config import IconConfig from iconcommons.logger import Logger additional_conf = { "log": { "logger": "iconservice", "colorLog": True, "level": "info", "filePath": f"./log/icon_service_{channel}.log", "outputType": "console|file" }, "scoreRootPath": f".storage/.score{amqp_key}_{channel}", "stateDbRootPath": f".storage/.statedb{amqp_key}_{channel}", "channel": channel, "amqpKey": amqp_key, "service": { "fee": True, "audit": True, "deployerWhiteList": False, "scorePackageValidator": False } } icon_conf = IconConfig("", default_icon_config) icon_conf.load() icon_conf.update(additional_conf) Logger.load_config(icon_conf) icon_service = IconService() icon_service.serve(config=icon_conf) Logger.info(f'==========IconService Done==========', 'IconServiceStandAlone') else: ScoreService(channel, score_package, amqp_target, amqp_key).serve()
def score_write_precommit_state(self, block: Block): logging.debug(f"call score commit {ChannelProperty().name} {block.height} {block.block_hash}") if util.channel_use_icx(ChannelProperty().name): request = { "blockHeight": block.height, "blockHash": block.block_hash, } request = convert_params(request, ParamType.write_precommit_state) stub = StubCollection().icon_score_stubs[ChannelProperty().name] stub.sync_task().write_precommit_state(request) return True else: block_commit_info = json.dumps({"block_height": block.height, "block_hash": block.block_hash}) stub = StubCollection().score_stubs[ChannelProperty().name] response = stub.sync_task().write_precommit_state(block_commit_info) if response.code == message_code.Response.success: return True else: logging.error(f"score db commit fail cause {response.message}") return False
def start_as_score(args): # apply default configure values channel = args.channel or conf.LOOPCHAIN_DEFAULT_CHANNEL score_package = args.score_package or conf.DEFAULT_SCORE_PACKAGE amqp_target = args.amqp_target or conf.AMQP_TARGET amqp_key = args.amqp_key or conf.AMQP_KEY if util.channel_use_icx(channel) and conf.USE_EXTERNAL_SCORE: if conf.EXTERNAL_SCORE_RUN_IN_LAUNCHER: from iconservice.icon_service import IconService from iconservice.icon_config import default_icon_config from iconcommons.icon_config import IconConfig from iconcommons.logger import Logger with open(conf.DEFAULT_SCORE_CONF_PATH) as file: load_conf = json.load(file) additional_conf = { "log": load_conf.get("log"), "scoreRootPath": f".storage/.score{amqp_key}_{channel}", "stateDbRootPath": f".storage/.statedb{amqp_key}_{channel}", "channel": channel, "amqpKey": amqp_key, "builtinScoreOwner": load_conf.get("builtinScoreOwner"), "service": load_conf.get("service") } icon_conf = IconConfig("", default_icon_config) icon_conf.load() icon_conf.update(additional_conf) Logger.load_config(icon_conf) icon_service = IconService() icon_service.serve(config=icon_conf) Logger.info(f'==========IconService Done==========', 'IconServiceStandAlone') else: ScoreService(channel, score_package, amqp_target, amqp_key).serve()
def score_invoke(self, _block: Block) -> dict or None: if util.channel_use_icx(ChannelProperty().name): method = "icx_sendTransaction" transactions = [] for tx in _block.confirmed_transaction_list: data = tx.icx_origin_data transaction = { "method": method, "params": data } transactions.append(transaction) request = { 'block': { 'blockHeight': _block.height, 'blockHash': _block.block_hash, 'prevBlockHash': _block.prev_block_hash, 'timestamp': _block.time_stamp }, '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.commit_state[ChannelProperty().name] = response['stateRootHash'] return response["txResults"] else: stub = StubCollection().score_stubs[ChannelProperty().name] response = stub.sync_task().score_invoke(_block) if response.code == message_code.Response.success: commit_state = pickle.loads(response.object) _block.commit_state = commit_state return json.loads(response.meta) return None
def __prevent_next_block_mismatch( self, next_block: Block, is_commit_state_validation: bool) -> bool: logging.debug(f"prevent_block_mismatch...") if util.channel_use_icx(self.__channel_name): 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.height: logging.debug(f"already invoked block in score...") return False elif score_last_block_height < next_block.height: for invoke_block_height in range(score_last_block_height + 1, next_block.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.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_result = self.__score_invoke_with_state_integrity( invoke_block, is_commit_state_validation) self.__add_tx_to_block_db(invoke_block, invoke_block_result) ObjectManager( ).channel_service.score_write_precommit_state(invoke_block) return True else: if score_last_block_height == next_block.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.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.height})/score({score_last_block_height})" ) return True