def main(): # Response server name as loopchain, not gunicorn. gunicorn.SERVER_SOFTWARE = 'loopchain' # Parse arguments. parser = argparse.ArgumentParser() parser.add_argument("-p", type=str, dest=ConfigKey.PORT, default=None, help="rest_proxy port") parser.add_argument("-c", type=str, dest=ConfigKey.CONFIG, default=None, help="json configure file path") args = parser.parse_args() conf_path = args.config if conf_path is not None: if not IconConfig.valid_conf_path(conf_path): print(f'invalid config file : {conf_path}') sys.exit(ExitCode.COMMAND_IS_WRONG.value) if conf_path is None: conf_path = str() conf = IconConfig(conf_path, default_rpcserver_config) conf.load() conf.update_conf(dict(vars(args))) Logger.load_config(conf) _run_async(_run(conf))
def start_as_rest_server(args): peer_port = args.port channel = conf.LOOPCHAIN_DEFAULT_CHANNEL amqp_key = args.amqp_key or conf.AMQP_KEY api_port = int(peer_port) + conf.PORT_DIFF_REST_SERVICE_CONTAINER from iconrpcserver.default_conf.icon_rpcserver_config import default_rpcserver_config from iconrpcserver.icon_rpcserver_cli import start_process, find_procs_by_params from iconcommons.icon_config import IconConfig from iconcommons.logger import Logger additional_conf = { "log": { "logger": "iconrpcserver", "colorLog": True, "level": "info", "filePath": "./log/iconrpcserver.log", "outputType": "console|file" }, "channel": channel, "port": api_port, "amqpKey": amqp_key, "gunicornWorkerCount": 1, "tbearsMode": False } rpcserver_conf = IconConfig("", default_rpcserver_config) rpcserver_conf.load() rpcserver_conf.update_conf(additional_conf) Logger.load_config(rpcserver_conf) if not find_procs_by_params(api_port): start_process(conf=rpcserver_conf) Logger.info("start_command done!, IconRpcServerCli")
def main(): # Parse arguments. try: parser = create_parser() except Exception as e: exit(f"Argument parsing exception : {e}") args = parser.parse_args(sys.argv[1:]) if args.config: conf_path = args.config if not IconConfig.valid_conf_path(conf_path): print(f'Invalid configuration file : {conf_path}') sys.exit(1) else: conf_path = str() # Load configuration conf = IconConfig(conf_path, tbears_server_config) conf.load() conf.update_conf(dict(vars(args))) Logger.load_config(conf) Logger.print_config(conf, TBEARS_BLOCK_MANAGER) setproctitle.setproctitle( f'{TBEARS_BLOCK_MANAGER}.{conf[ConfigKey.CHANNEL]}.{conf[ConfigKey.AMQP_KEY]}' ) # run block_manager service block_manager = BlockManager(conf=conf) block_manager.serve() Logger.info('===============tbears block_manager done================', TBEARS_BLOCK_MANAGER)
def get_icon_conf(command: str, args: dict = None) -> dict: """Load config file using IconConfig instance config file is loaded as below priority system config -> default config -> user config -> user input config (higher priority) :param command: command name (e.g. start) :param args: user input command (converted to dictionary type) :return: command configuration """ # load configurations conf = IconConfig(FN_SERVER_CONF, copy.deepcopy(tbears_server_config)) # load config file conf.load(config_path=args.get('config', None) if args else None) # move command config if command in conf: conf.update_conf(conf[command]) del conf[command] # load user argument if args: conf.update_conf(args) # add default configuration file if args.get('config', None) is None: if os.path.exists(FN_SERVER_CONF): conf['config'] = FN_SERVER_CONF return conf
def open( self, config_path: str, fee: bool = True, audit: bool = True, deployer_whitelist: bool = False, score_package_validator: bool = False, builtin_score_owner: str = "", ): conf = IconConfig("", default_icon_config) if config_path != "": conf.load(config_path) conf.update_conf({ "builtinScoreOwner": builtin_score_owner, "service": { "fee": fee, "audit": audit, "scorePackageValidator": score_package_validator, "deployerWhiteList": deployer_whitelist, }, }) Logger.load_config(conf) self._engine.open(conf)
def setUp(self): self._state_db_root_path = '.db' self._score_root_path = '.score' rmtree(self._score_root_path) rmtree(self._state_db_root_path) engine = IconServiceEngine() conf = IconConfig("", default_icon_config) conf.load() conf.update_conf({ ConfigKey.BUILTIN_SCORE_OWNER: str(create_address(AddressPrefix.EOA)), ConfigKey.SCORE_ROOT_PATH: self._score_root_path, ConfigKey.STATE_DB_ROOT_PATH: self._state_db_root_path }) # engine._load_builtin_scores = Mock() # engine._init_global_value_by_governance_score = Mock() engine.open(conf) self._engine = engine self._genesis_address = create_address(AddressPrefix.EOA) self._treasury_address = create_address(AddressPrefix.EOA) self._governance_score_address =\ Address.from_string('cx0000000000000000000000000000000000000001') self.from_ = self._genesis_address self._to = create_address(AddressPrefix.EOA) self._icon_score_address = create_address(AddressPrefix.CONTRACT) self._total_supply = 100 * 10**18 accounts = [{ 'name': 'god', 'address': self._genesis_address, 'balance': self._total_supply }, { 'name': 'treasury', 'address': self._treasury_address, 'balance': 0 }] block = Block(0, create_block_hash(), 0, None) tx = { 'method': '', 'params': { 'txHash': create_tx_hash() }, 'genesisData': { 'accounts': accounts } } tx_lists = [tx] self._engine.invoke(block, tx_lists) self._engine.commit(block) self.genesis_block = block
def main(): # Response server name as loopchain, not gunicorn. gunicorn.SERVER_SOFTWARE = 'loopchain' # Parse arguments. parser = argparse.ArgumentParser() parser.add_argument("-p", type=str, dest=ConfigKey.PORT, default=None, help="rest_proxy port") parser.add_argument("-c", type=str, dest=ConfigKey.CONFIG, default=None, help="json configure file path") parser.add_argument("-at", type=str, dest=ConfigKey.AMQP_TARGET, default=None, help="amqp target info [IP]:[PORT]") parser.add_argument( "-ak", type=str, dest=ConfigKey.AMQP_KEY, default=None, help= "key sharing peer group using queue name. use it if one more peers connect one MQ" ) parser.add_argument("-ch", dest=ConfigKey.CHANNEL, default=None, help="icon score channel") parser.add_argument("-tbears", dest=ConfigKey.TBEARS_MODE, action='store_true', help="tbears mode") args = parser.parse_args() conf_path = args.config if conf_path is not None: if not IconConfig.valid_conf_path(conf_path): print(f'invalid config file : {conf_path}') sys.exit(ExitCode.COMMAND_IS_WRONG.value) if conf_path is None: conf_path = str() conf = IconConfig(conf_path, default_rpcserver_config) conf.load() conf.update_conf(dict(vars(args))) Logger.load_config(conf) _run_async(_check_rabbitmq(conf[ConfigKey.AMQP_TARGET])) _run_async(_run(conf))
def _init_logger(self, args): from iconcommons.icon_config import IconConfig if args.verbose: conf = IconConfig(None, tbears_server_config) conf.load() if 'console' not in conf['log']['outputType']: conf['log'][ 'outputType'] = conf['log']['outputType'] + "|console" Logger.load_config(conf)
def setUp(self): self.cmd = Command() self.project_name = 'sample_prj' self.project_class = 'SampleClass' self.start_conf = None tbears_config_path = os.path.join(TEST_UTIL_DIRECTORY, f'test_tbears_server_config.json') start_conf = IconConfig(tbears_config_path, tbears_server_config) start_conf.load() start_conf['config'] = tbears_config_path self.start_conf = start_conf
def setUpClass(cls): conf = IconConfig(str(), default_icon_config) conf.load() IconLoggerUtil.apply_config(icon_logger, conf) IconLoggerUtil.print_config(icon_logger, conf) file_path = os.path.join(os.path.dirname(__file__), 'logger.json') conf = IconConfig(file_path, default_icon_config) conf.load() IconLoggerUtil.apply_config(icon_logger, conf) IconLoggerUtil.print_config(icon_logger, conf)
def setUpClass(cls): conf = IconConfig(str(), default_icon_config) conf.load() Logger.load_config(conf) Logger.print_config(conf, TAG) file_path = os.path.join(os.path.dirname(__file__), 'logger.json') conf = IconConfig(file_path, default_icon_config) conf.load() Logger.load_config(conf) Logger.print_config(conf, TAG)
def test_duplicated_tx(self): # test start, deploy, stop, clean command conf = self.cmd.cmdUtil.get_init_args(project=self.project_name, score_class=self.project_class) # init self.cmd.cmdUtil.init(conf) # start tbears_config_path = os.path.join(TEST_UTIL_DIRECTORY, f'test_tbears_server_config.json') start_conf = IconConfig(tbears_config_path, tbears_server_config) start_conf.load() start_conf['config'] = tbears_config_path self.start_conf = start_conf self.cmd.cmdServer.start(start_conf) self.assertTrue(self.cmd.cmdServer.is_service_running()) # prepare to send genesis_info = start_conf['genesis']['accounts'][0] from_addr = genesis_info['address'] uri = f'http://127.0.0.1:{start_conf["port"]}/api/v3' uri, version = uri_parser(uri) icon_service = IconService(HTTPProvider(uri, version)) to_addr = f'hx{"d" * 40}' timestamp = int(time.time() * 10**6) transaction = TransactionBuilder()\ .from_(from_addr)\ .to(to_addr)\ .timestamp(timestamp)\ .step_limit(convert_hex_str_to_int('0x100000'))\ .build() wallet = KeyWallet.create() signed_transaction = SignedTransaction(transaction, wallet) signed_transaction.signed_transaction_dict['signature'] = 'sig' # send transaction response = send_transaction_with_logger(icon_service, signed_transaction, uri) self.assertTrue('result' in response) # send again response = send_transaction_with_logger(icon_service, signed_transaction, uri) self.assertTrue('error' in response) self.assertEqual( responseCodeMap[Response.fail_tx_invalid_duplicated_hash][1], response['error']['message'])
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 conf_path = conf.CONF_PATH_ICONSERVICE_DEV if args.radio_station_target: if args.radio_station_target == conf.URL_CITIZEN_TESTNET: conf_path = conf.CONF_PATH_ICONSERVICE_TESTNET elif args.radio_station_target == conf.URL_CITIZEN_MAINNET: conf_path = conf.CONF_PATH_ICONSERVICE_MAINNET if 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_path) as file: load_conf = json.load(file) additional_conf = { "log": load_conf.get("log"), "scoreRootPath": load_conf.get("scoreRootPath") + f"{amqp_key}_{channel}", "stateDbRootPath": load_conf.get("stateDbRootPath") + f"{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 main(): parser = argparse.ArgumentParser() parser.add_argument("-sc", dest=ConfigKey.SCORE_ROOT_PATH, type=str, default=None, help="icon score root path example : .score") parser.add_argument("-st", dest=ConfigKey.STATE_DB_ROOT_PATH, type=str, default=None, help="icon score state db root path example : .statedb") parser.add_argument("-ch", dest=ConfigKey.CHANNEL, type=str, default=None, help="icon score channel") parser.add_argument("-ak", dest=ConfigKey.AMQP_KEY, type=str, default=None, help="icon score amqp_key : [amqp_key]") parser.add_argument("-at", dest=ConfigKey.AMQP_TARGET, type=str, default=None, help="icon score amqp_target : [127.0.0.1]") parser.add_argument("-c", dest=ConfigKey.CONFIG, type=str, default=None, help="icon score config") parser.add_argument("-tbears", dest=ConfigKey.TBEARS_MODE, action='store_true', help="tbears mode") parser.add_argument("-steptrace", dest=ConfigKey.STEP_TRACE_FLAG, action="store_true", help="enable step tracing") args = parser.parse_args() args_params = dict(vars(args)) del args_params['config'] setproctitle.setproctitle(ICON_SERVICE_PROCTITLE_FORMAT.format(**args_params)) conf_path = args.config if conf_path is not None: if not IconConfig.valid_conf_path(conf_path): print(f'invalid config file : {conf_path}') sys.exit(ExitCode.INVALID_COMMAND.value) if conf_path is None: conf_path = str() conf = IconConfig(conf_path, copy.deepcopy(default_icon_config)) conf.load() conf.update_conf(args_to_dict(args)) Logger.load_config(conf) if not check_config(conf, default_icon_config): Logger.error(tag=_TAG, msg=f"Invalid Config") sys.exit(ExitCode.INVALID_CONFIG.value) Logger.print_config(conf, _TAG) _run_async(_check_rabbitmq(conf[ConfigKey.AMQP_TARGET])) icon_service = IconService() icon_service.serve(config=conf) Logger.info(f'==========IconService Done==========', _TAG)
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 test_duplicated_tx(self): # test start, deploy, stop, clean command conf = self.cmd.cmdUtil.get_init_args(project=self.project_name, score_class=self.project_class) # init self.cmd.cmdUtil.init(conf) # start tbears_config_path = os.path.join(TEST_UTIL_DIRECTORY, f'test_tbears_server_config.json') start_conf = IconConfig(tbears_config_path, tbears_server_config) start_conf.load() start_conf['config'] = tbears_config_path self.start_conf = start_conf self.cmd.cmdServer.start(start_conf) self.assertTrue(self.cmd.cmdServer.is_service_running()) # prepare to send genesis_info = start_conf['genesis']['accounts'][0] from_addr = genesis_info['address'] icon_jsonrpc = IconJsonrpc.from_string(from_addr) icon_client = IconClient( f'http://127.0.0.1:{start_conf["port"]}/api/v3') to_addr = f'hx{"d"*40}' timestamp = hex(int(time.time() * 10**6)) # send transaction request = icon_jsonrpc.sendTransaction(to=to_addr, timestamp=timestamp, step_limit='0x100000') response = icon_client.send(request) self.assertTrue('result' in response) # send again response = icon_client.send(request) self.assertTrue('error' in response) self.assertEqual( responseCodeMap[Response.fail_tx_invalid_duplicated_hash][1], response['error']['message'])
def start_as_rest_server(args): peer_port = args.port channel = conf.LOOPCHAIN_DEFAULT_CHANNEL amqp_key = args.amqp_key or conf.AMQP_KEY api_port = int(peer_port) + conf.PORT_DIFF_REST_SERVICE_CONTAINER conf_path = conf.CONF_PATH_ICONRPCSERVER_DEV if args.radio_station_target: if args.radio_station_target == conf.URL_CITIZEN_TESTNET: conf_path = conf.CONF_PATH_ICONRPCSERVER_TESTNET elif args.radio_station_target == conf.URL_CITIZEN_MAINNET: conf_path = conf.CONF_PATH_ICONRPCSERVER_MAINNET from iconrpcserver.default_conf.icon_rpcserver_config import default_rpcserver_config from iconrpcserver.icon_rpcserver_cli import start_process, find_procs_by_params from iconcommons.icon_config import IconConfig from iconcommons.logger import Logger with open(conf_path) as file: load_conf = json.load(file) additional_conf = { "log": load_conf.get("log"), "channel": channel, "port": api_port, "amqpKey": amqp_key, "gunicornWorkerCount": 1, "tbearsMode": False } rpcserver_conf = IconConfig("", default_rpcserver_config) rpcserver_conf.load() rpcserver_conf.update_conf(additional_conf) Logger.load_config(rpcserver_conf) if not find_procs_by_params(api_port): start_process(conf=rpcserver_conf) Logger.info("start_command done!, IconRpcServerCli")
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 test_deploy_command(self): conf = self.cmd.cmdUtil.get_init_args(project=self.project_name, score_class=self.project_class) self.cmd.cmdUtil.init(conf) # make project zip file zip_dir(self.project_name) # start tbears_config_path = os.path.join(TEST_UTIL_DIRECTORY, f'test_tbears_server_config.json') start_conf = IconConfig(tbears_config_path, tbears_server_config) start_conf.load() start_conf['config'] = tbears_config_path self.start_conf = start_conf self.cmd.cmdServer.start(start_conf) self.assertTrue(self.cmd.cmdServer.is_service_running()) # deploy - install success #1 (without stepLimit) args = {"from": "hxef73db5d0ad02eb1fadb37d0041be96bfa56d4e6"} conf = self.cmd.cmdScore.get_icon_conf(command='deploy', project=self.project_name, args=args) deploy_response = self.deploy_cmd(conf=conf) self.assertEqual(deploy_response.get('error', False), False) # check result tx_hash = deploy_response['result'] conf = self.cmd.cmdWallet.get_icon_conf('txresult', {'hash': tx_hash}) transaction_result_response = self.cmd.cmdWallet.txresult(conf) score_address = transaction_result_response['result']['scoreAddress'] self.assertFalse(transaction_result_response.get('error', False)) # deploy - install success #2 (without stepLimit, with keystore) args['keyStore'] = os.path.join(TEST_UTIL_DIRECTORY, 'test_keystore') conf = self.cmd.cmdScore.get_icon_conf(command='deploy', project=self.project_name, args=args) deploy_response = self.deploy_cmd(conf=conf, password='******') self.assertEqual(deploy_response.get('error', False), False) # check result tx_hash = deploy_response['result'] conf = self.cmd.cmdWallet.get_icon_conf('txresult', {'hash': tx_hash}) transaction_result_response = self.cmd.cmdWallet.txresult(conf) score_address = transaction_result_response['result']['scoreAddress'] self.assertFalse(transaction_result_response.get('error', False)) # deploy - install fail #1 (apply stepLimit with command line argument) args["stepLimit"] = "0x1" conf = self.cmd.cmdScore.get_icon_conf(command='deploy', project=self.project_name, args=args) deploy_response = self.deploy_cmd(conf=conf, password='******') self.assertIsInstance(deploy_response.get('error', False), dict) # deploy - install fail #2 (apply stepLimit with config file) tbears_cli_config_step_set_path = os.path.join( TEST_UTIL_DIRECTORY, 'test_tbears_cli_config_step_set.json') args = {"config": tbears_cli_config_step_set_path} conf = self.cmd.cmdScore.get_icon_conf(command='deploy', project=self.project_name, args=args) deploy_response = self.deploy_cmd(conf=conf) self.assertIsInstance(deploy_response.get('error', False), dict) # deploy - update case1 (not using stepLimit config) args = { "from": "hxef73db5d0ad02eb1fadb37d0041be96bfa56d4e6", "to": score_address } conf = self.cmd.cmdScore.get_icon_conf(command='deploy', project=self.project_name, args=args) deploy_response = self.deploy_cmd(conf=conf) self.assertEqual(deploy_response.get('error', False), False) # check result tx_hash = deploy_response['result'] conf = self.cmd.cmdWallet.get_icon_conf('txresult', {'hash': tx_hash}) transaction_result_response = self.cmd.cmdWallet.txresult(conf) score_address = transaction_result_response['result']['scoreAddress'] self.assertFalse(transaction_result_response.get('error', False)) # deploy - update case2 (using stepLimit config with command line argument) args["stepLimit"] = "0x1" conf = self.cmd.cmdScore.get_icon_conf(command='deploy', project=self.project_name, args=args) deploy_response = self.deploy_cmd(conf=conf) self.assertIsInstance(deploy_response.get('error', False), dict) # deploy - update case3 (using stepLimit config with config file) tbears_cli_config_step_set_path = os.path.join( TEST_UTIL_DIRECTORY, 'test_tbears_cli_config_step_set.json') args = {"config": tbears_cli_config_step_set_path, "to": score_address} conf = self.cmd.cmdScore.get_icon_conf(command='deploy', project=self.project_name, args=args) deploy_response = self.deploy_cmd(conf=conf) self.assertIsInstance(deploy_response.get('error', False), dict) # stop self.cmd.cmdServer.stop(None) self.assertFalse(self.check_server()) self.assertTrue(os.path.exists(TBEARS_CLI_ENV)) # clear self.cmd.cmdScore.clear(start_conf) self.assertFalse(os.path.exists(start_conf['scoreRootPath'])) self.assertFalse(os.path.exists(start_conf['stateDbRootPath'])) self.assertFalse(os.path.exists(TBEARS_CLI_ENV))
def main(): parser = argparse.ArgumentParser(prog='iconrpcserver_cli.py', usage=f""" ========================== iconrpcserver server ========================== iconrpcserver commands: start : iconrpcserver start stop : iconrpcserver stop -p : rest_proxy port -c : json configure file path -at : amqp target info [IP]:[PORT] -ak : key sharing peer group using queue name. use it if one more peers connect one MQ -ch : loopchain channel ex) loopchain_default -fg : foreground process -tbears : tbears mode """) parser.add_argument('command', type=str, nargs='*', choices=['start', 'stop'], help='rest type [start|stop]') parser.add_argument("-p", type=str, dest=ConfigKey.PORT, default=None, help="rest_proxy port") parser.add_argument("-c", type=str, dest=ConfigKey.CONFIG, default=None, help="json configure file path") parser.add_argument("-at", type=str, dest=ConfigKey.AMQP_TARGET, default=None, help="amqp target info [IP]:[PORT]") parser.add_argument( "-ak", type=str, dest=ConfigKey.AMQP_KEY, default=None, help= "key sharing peer group using queue name. use it if one more peers connect one MQ" ) parser.add_argument("-ch", dest=ConfigKey.CHANNEL, default=None, help="icon score channel") parser.add_argument("-fg", dest='foreground', action='store_true', help="icon rpcserver run foreground") parser.add_argument("-tbears", dest=ConfigKey.TBEARS_MODE, action='store_true', help="tbears mode") args = parser.parse_args() if len(args.command) < 1: parser.print_help() sys.exit(ExitCode.COMMAND_IS_WRONG.value) conf_path = args.config if conf_path is not None: if not IconConfig.valid_conf_path(conf_path): print(f'invalid config file : {conf_path}') sys.exit(ExitCode.COMMAND_IS_WRONG.value) if conf_path is None: conf_path = str() conf = IconConfig(conf_path, default_rpcserver_config) conf.load() conf.update_conf(dict(vars(args))) Logger.load_config(conf) command = args.command[0] if command == 'start' and len(args.command) == 1: result = start(conf) elif command == 'stop' and len(args.command) == 1: result = stop(conf) else: parser.print_help() result = ExitCode.COMMAND_IS_WRONG.value sys.exit(result)
def main(): parser = argparse.ArgumentParser(prog='icon_service_cli.py', usage=f""" ========================== iconservice ========================== iconservice commands: start : iconservice start stop : iconservice stop -c : json configure file path -sc : icon score root path ex).score -st : icon score state db root path ex).state -at : amqp target info [IP]:[PORT] -ak : key sharing peer group using queue name. use it if one more peers connect one MQ -ch : loopchain channel ex) loopchain_default -fg : foreground process -tbears : tbears mode """) parser.add_argument('command', type=str, nargs='*', choices=['start', 'stop'], help='iconservice type [start|stop]') parser.add_argument("-sc", dest=ConfigKey.SCORE_ROOT_PATH, type=str, default=None, help="icon score root path example : .score") parser.add_argument("-st", dest=ConfigKey.STATE_DB_ROOT_PATH, type=str, default=None, help="icon score state db root path example : .statedb") parser.add_argument("-ch", dest=ConfigKey.CHANNEL, type=str, default=None, help="icon score channel") parser.add_argument("-ak", dest=ConfigKey.AMQP_KEY, type=str, default=None, help="icon score amqp_key : [amqp_key]") parser.add_argument("-at", dest=ConfigKey.AMQP_TARGET, type=str, default=None, help="icon score amqp_target : [127.0.0.1]") parser.add_argument("-c", dest=ConfigKey.CONFIG, type=str, default=None, help="icon score config") parser.add_argument("-fg", dest='foreground', action='store_true', help="icon score service run foreground") parser.add_argument("-tbears", dest=ConfigKey.TBEARS_MODE, action='store_true', help="tbears mode") args = parser.parse_args() if len(args.command) < 1: parser.print_help() sys.exit(ExitCode.COMMAND_IS_WRONG.value) conf_path = args.config if conf_path is not None: if not IconConfig.valid_conf_path(conf_path): print(f'invalid config file : {conf_path}') sys.exit(ExitCode.COMMAND_IS_WRONG.value) if conf_path is None: conf_path = str() conf = IconConfig(conf_path, default_icon_config) conf.load() conf.update_conf(dict(vars(args))) Logger.load_config(conf) command = args.command[0] if command == 'start' and len(args.command) == 1: result = _start(conf) elif command == 'stop' and len(args.command) == 1: result = _stop(conf) else: parser.print_help() result = ExitCode.COMMAND_IS_WRONG.value sys.exit(result)
def test_start_deploy_transfer_result_stop_clean(self): # test start, deploy, stop, clean command conf = self.cmd.cmdUtil.get_init_args(project=self.project_name, score_class=self.project_class) # init self.cmd.cmdUtil.init(conf) # make project zip file zip_dir(self.project_name) # start tbears_config_path = os.path.join(TEST_UTIL_DIRECTORY, f'test_tbears_server_config.json') start_conf = IconConfig(tbears_config_path, tbears_server_config) start_conf.load() start_conf['config'] = tbears_config_path self.start_conf = start_conf self.cmd.cmdServer.start(start_conf) self.assertTrue(self.cmd.cmdServer.is_service_running()) # totalsup total_sup = get_total_supply(tbears_config_path) conf = IconConfig(FN_CLI_CONF, tbears_cli_config) total_supply_response = self.cmd.cmdWallet.totalsupply(conf) self.assertEqual(total_sup, total_supply_response['result']) # sendtx - get step price from governance SCORE conf = self.cmd.cmdWallet.get_icon_conf( 'call', {"json_file": os.path.join(TEST_UTIL_DIRECTORY, 'call.json')}) call_response_json = self.cmd.cmdWallet.call(conf) self.assertFalse(call_response_json.get('error', False)) # get balance - get balance of genesis address genesis_info = start_conf['genesis']['accounts'][0] conf['address'] = genesis_info['address'] genesis_balance = genesis_info['balance'] get_balance_response = self.cmd.cmdWallet.balance(conf) self.assertEqual(genesis_balance, get_balance_response['result']) # get balance - get balance of treasury address treasury_info = start_conf['genesis']['accounts'][1] conf['address'] = treasury_info['address'] treasury_balance = treasury_info['balance'] get_balance_response = self.cmd.cmdWallet.balance(conf) self.assertEqual(treasury_balance, get_balance_response['result']) # deploy - f"-m install" args = {"from": "hxef73db5d0ad02eb1fadb37d0041be96bfa56d4e6"} conf = self.cmd.cmdScore.get_icon_conf(command='deploy', project=self.project_name, args=args) deploy_response = self.deploy_cmd(conf=conf) self.assertEqual(deploy_response.get('error', False), False) # result (query transaction result) # response (after deploy) contains tx_hash. # below is check if the tx_hash is valid using 'txresult' method tx_hash = deploy_response['result'] conf = self.cmd.cmdWallet.get_icon_conf('txresult', {'hash': tx_hash}) transaction_result_response = self.cmd.cmdWallet.txresult(conf) self.assertFalse(transaction_result_response.get('error', False)) # scoreapi score_address = transaction_result_response['result']['scoreAddress'] conf['address'] = score_address score_api_response = self.cmd.cmdWallet.scoreapi(conf) self.assertFalse(score_api_response.get('error', False)) # deploy - f"-m update --to socreAddress from_transactionResult -c tbears_cli_config.json" scoreAddress = transaction_result_response['result']['scoreAddress'] conf = self.cmd.cmdScore.get_icon_conf(command='deploy', project=self.project_name, args=args) conf['mode'] = 'update' conf['to'] = scoreAddress conf['conf'] = './tbears_cli_config.json' deploy_response = self.deploy_cmd(conf=conf) self.assertEqual(deploy_response.get('error', False), False) # deploy - f"-m update --to invalid_scoreAddress -c tbears_cli_config.json" # when invalid scoreAddress, response data should contain error data invalid_score_address = 'cx02b13428a8aef265fbaeeb37394d3ae8727f7a19' invalid_conf = deepcopy(conf) invalid_conf['mode'] = 'update' invalid_conf['to'] = invalid_score_address invalid_conf['conf'] = './tbears_cli_config.json' invalid_deploy_response = self.deploy_cmd(conf=invalid_conf) self.assertIsNotNone(invalid_deploy_response.get('error', None)) # result (query transaction result) tx_hash = deploy_response['result'] conf = self.cmd.cmdWallet.get_icon_conf('txresult', {'hash': tx_hash}) transaction_result_response = self.cmd.cmdWallet.txresult(conf) self.assertFalse(transaction_result_response.get('error', False)) self.assertEqual(transaction_result_response['result']['status'], "0x1") self.assertEqual(transaction_result_response['result']['scoreAddress'], scoreAddress) # deploy - f"-m install -k test_keystore" conf = self.cmd.cmdScore.get_icon_conf(command='deploy', project=self.project_name) conf['keyStore'] = os.path.join(TEST_UTIL_DIRECTORY, 'test_keystore') deploy_response = self.deploy_cmd(conf=conf, password='******') self.assertEqual(deploy_response.get('error', False), False) # result (query transaction result) tx_hash = deploy_response['result'] conf = self.cmd.cmdWallet.get_icon_conf('txresult', {'hash': tx_hash}) transaction_result_response = self.cmd.cmdWallet.txresult(conf) self.assertFalse(transaction_result_response.get('error', False)) self.assertEqual(transaction_result_response['result']['status'], "0x1") # deploy - update with zip file f"-m update -k test_keystore --to scoreAddres_from_transactionResult" scoreAddress = transaction_result_response['result']['scoreAddress'] conf = self.cmd.cmdScore.get_icon_conf(command='deploy', project=self.project_name) conf['keyStore'] = os.path.join(TEST_UTIL_DIRECTORY, 'test_keystore') conf['mode'] = 'update' conf['to'] = scoreAddress conf['project'] = f'{self.project_name}.zip' deploy_response = self.deploy_cmd(conf=conf, password='******') self.assertEqual(deploy_response.get('error', False), False) invalid_tx_hash = '0x3d6fa810d782a3b3aa6e4a95f5ac48d8bfa096366b3c2ba2922f49cccf3ac6b5' invalid_conf = self.cmd.cmdWallet.get_icon_conf( 'txresult', {'hash': invalid_tx_hash}) transaction_result_response = self.cmd.cmdWallet.txresult(invalid_conf) self.assertIsNotNone(transaction_result_response.get('error', None)) # result (query transaction result) tx_hash = deploy_response['result'] conf = self.cmd.cmdWallet.get_icon_conf('txresult', {'hash': tx_hash}) transaction_result_response = self.cmd.cmdWallet.txresult(conf) self.assertFalse(transaction_result_response.get('error', False)) self.assertEqual(transaction_result_response['result']['status'], "0x1") self.assertEqual(transaction_result_response['result']['scoreAddress'], scoreAddress) # txbyhash (query transaction) conf = self.cmd.cmdWallet.get_icon_conf('txbyhash', {'hash': tx_hash}) txbyhash_response = self.cmd.cmdWallet.txbyhash(conf) txbyhash_response_result = txbyhash_response['result'] self.assertIn('from', txbyhash_response_result) self.assertIn('to', txbyhash_response_result) self.assertIn('value', txbyhash_response_result) # lastblock response = self.cmd.cmdWallet.lastblock(conf) self.assertIn('result', response) conf['hash'] = f"0x{response['result']['block_hash']}" conf['height'] = hex(response['result']['height']) # blockbyheight response_height = self.cmd.cmdWallet.blockbyheight(conf) self.assertIn('result', response_height) self.assertEqual(hex(response_height['result']['height']), conf['height']) # blockbyhash response_hash = self.cmd.cmdWallet.blockbyhash(conf) self.assertIn('result', response_hash) self.assertEqual(f"0x{response_hash['result']['block_hash']}", conf['hash']) # transfer key_path = os.path.join(TEST_UTIL_DIRECTORY, 'test_keystore') conf = self.cmd.cmdWallet.get_icon_conf( 'transfer', { 'keyStore': key_path, 'to': f'hx123{"0"*37}', 'value': 0.3e2, 'password': '******' }) transfer_response_json = self.cmd.cmdWallet.transfer(conf) self.assertFalse(transfer_response_json.get('error', False)) # sendtx conf = self.cmd.cmdWallet.get_icon_conf( 'sendtx', { "json_file": os.path.join(TEST_UTIL_DIRECTORY, 'send.json'), "keyStore": key_path, 'password': '******' }) sendtx_response_json = self.cmd.cmdWallet.sendtx(conf) self.assertFalse(sendtx_response_json.get('error', False)) # stop self.cmd.cmdServer.stop(None) self.assertFalse(self.check_server()) self.assertTrue(os.path.exists(TBEARS_CLI_ENV)) # clear self.cmd.cmdScore.clear(start_conf) self.assertFalse(os.path.exists(start_conf['scoreRootPath'])) self.assertFalse(os.path.exists(start_conf['stateDbRootPath'])) self.assertFalse(os.path.exists(TBEARS_CLI_ENV)) shutil.rmtree(f'./{self.project_name}')
class TestIconClient(unittest.TestCase): def setUp(self): self.cmd = Command() tbears_server_config_path = os.path.join( TEST_UTIL_DIRECTORY, 'test_tbears_server_config.json') self.conf = IconConfig(tbears_server_config_path, tbears_server_config) self.conf.load() self.conf['config'] = tbears_server_config_path self.cmd.cmdServer.start(self.conf) # Check server started (before test Icon client, sever has to be started) self.assertTrue(self.check_server()) def check_server(self): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # if socket is connected, the result code is 0 (false). result = sock.connect_ex(('127.0.0.1', 9000)) sock.close() return result == 0 def tearDown(self): if self.check_server(): self.cmd.cmdServer.stop(self.conf) if os.path.exists('exc'): shutil.rmtree('exc') if os.path.exists('tbears.log'): os.remove('tbears.log') def test_send_request_to_server(self): # Correct request payload = {"jsonrpc": "2.0", "method": "icx_getTotalSupply", "id": 111} client = IconClient('http://127.0.0.1:9000/api/v3') response = client.send(payload) # the return type should 'dict' expected_type = type({}) self.assertEqual(type(response), expected_type) self.assertIsNotNone(response['result']) # Incorrect request: input url which is omitted port number payload = {"jsonrpc": "2.0", "method": "icx_getTotalSupply", "id": 111} client = IconClient('http://127.0.0.1:/api/v3') # check get response correctly, don't check the response data self.assertRaises(Exception, client.send, payload) # Incorrect request: invalid url to working server payload = {"jsonrpc": "2.0", "method": "icx_getTotalSupply", "id": 111} client = IconClient('http://127.0.0.1:9000/api/invalidUrl') # check get response correctly, don't check the response data self.assertRaises(IconClientException, client.send, payload) # Incorrect request: invalid url to not working service payload = {"jsonrpc": "2.0", "method": "icx_getTotalSupply", "id": 111} client = IconClient('http://127.0.0.1:19001/api/invalidUrl') # check get response correctly, don't check the response data self.assertRaises(Exception, client.send, payload) # Bad request: invalid payload data (nonexistent method name) incorrect_payload = { "jsonrpc": "2.0", "method": "icx_invalid_requests", "id": 111 } client = IconClient('http://127.0.0.1:9000/api/v3') response = client.send(incorrect_payload) self.assertIsNotNone(response['error']) # Bad request: insufficient payload data (method is not set) insufficient_payload = {"jsonrpc": "2.0", "id": 111} client = IconClient('http://127.0.0.1:9000/api/v3') response = client.send(insufficient_payload) self.assertIsNotNone(response['error']) # requests when server stopped self.cmd.cmdServer.stop(self.conf) payload = {"jsonrpc": "2.0", "method": "icx_getTotalSupply", "id": 111} client = IconClient('http://127.0.0.1:9000/api/v3') self.assertRaises(Exception, client.send, payload) self.cmd.cmdScore.clear(self.conf)
class TestCommandWallet(unittest.TestCase): def setUp(self): self.cmd = Command() # start tbears_config_path = os.path.join(TEST_UTIL_DIRECTORY, f'test_tbears_server_config.json') self.start_conf = IconConfig(tbears_config_path, tbears_server_config) self.start_conf.load() self.start_conf['config'] = tbears_config_path self.start_conf = self.start_conf self.cmd.cmdServer.start(self.start_conf) self.assertTrue(self.cmd.cmdServer.is_service_running()) def tearDown(self): # stop self.cmd.cmdServer.stop(None) self.assertFalse(self.check_server()) self.assertTrue(os.path.exists(TBEARS_CLI_ENV)) # clear self.cmd.cmdScore.clear(self.start_conf) self.assertFalse(os.path.exists(self.start_conf['scoreRootPath'])) self.assertFalse(os.path.exists(self.start_conf['stateDbRootPath'])) self.assertFalse(os.path.exists(TBEARS_CLI_ENV)) try: if os.path.exists(FN_CLI_CONF): os.remove(FN_CLI_CONF) if os.path.exists(FN_SERVER_CONF): os.remove(FN_SERVER_CONF) if os.path.exists('./tbears.log'): os.remove('./tbears.log') self.cmd.cmdServer.stop(None) if os.path.exists('exc'): shutil.rmtree('exc') self.cmd.cmdScore.clear( self.start_conf if self.start_conf else tbears_server_config) except: pass @staticmethod def check_server(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # if socket is connected, the result code is 0 (false). result = sock.connect_ex(('127.0.0.1', 9000)) sock.close() return result == 0 def tx_command(self, command: str, conf: dict, password: str = None) -> dict: conf['password'] = password command_handler = getattr(self.cmd.cmdWallet, command) response = command_handler(conf=conf) # Wait until block_manager confirm block. block_manager for test confirm every second time.sleep(2) return response def test_transfer_command(self): # transfer success #1 (without stepLimit) args = { "to": f"hx{'a'*40}", "value": 1, "from": "hxef73db5d0ad02eb1fadb37d0041be96bfa56d4e6" } conf = self.cmd.cmdWallet.get_icon_conf(command='transfer', args=args) response = self.tx_command("transfer", conf=conf) self.assertEqual(response.get('error', False), False) # check result tx_hash = response['result'] conf = self.cmd.cmdWallet.get_icon_conf('txresult', {'hash': tx_hash}) transaction_result_response = self.cmd.cmdWallet.txresult(conf) self.assertFalse(transaction_result_response.get('error', False)) # transfer success #2 (without stepLimit, with keystore) args = { "to": f"hx{'a'*40}", "value": 1, "from": "hxef73db5d0ad02eb1fadb37d0041be96bfa56d4e6", "keyStore": os.path.join(TEST_UTIL_DIRECTORY, 'test_keystore') } conf = self.cmd.cmdWallet.get_icon_conf(command='transfer', args=args) response = self.tx_command("transfer", conf=conf, password='******') self.assertEqual(response.get('error', False), False) # check result tx_hash = response['result'] conf = self.cmd.cmdWallet.get_icon_conf('txresult', {'hash': tx_hash}) transaction_result_response = self.cmd.cmdWallet.txresult(conf) self.assertFalse(transaction_result_response.get('error', False)) # transfer fail #1 (apply stepLimit config with command line argument) args = { "stepLimit": "0x1", "to": f"hx{'a'*40}", "value": 1, "from": "hxef73db5d0ad02eb1fadb37d0041be96bfa56d4e6" } conf = self.cmd.cmdScore.get_icon_conf(command='transfer', args=args) response = self.tx_command("transfer", conf=conf) self.assertIsInstance(response.get('error', False), dict) # transfer fail #2 (apply stepLimit config with config file) tbears_cli_config_step_set_path = os.path.join( TEST_UTIL_DIRECTORY, 'test_tbears_cli_config_step_set.json') args = { "config": tbears_cli_config_step_set_path, "to": f"hx{'a'*40}", "value": 1, "from": "hxef73db5d0ad02eb1fadb37d0041be96bfa56d4e6" } conf = self.cmd.cmdScore.get_icon_conf(command='transfer', args=args) response = self.tx_command("transfer", conf=conf) self.assertIsInstance(response.get('error', False), dict) def test_sendtx_command(self): # use the stepLimit in the json file send_json_path = os.path.join(TEST_UTIL_DIRECTORY, 'send.json') args = {"json_file": send_json_path} conf = self.cmd.cmdWallet.get_icon_conf(command='sendtx', args=args) response = self.tx_command("sendtx", conf=conf) self.assertEqual(response.get('error', False), False) # check result tx_hash = response['result'] conf = self.cmd.cmdWallet.get_icon_conf('txresult', {'hash': tx_hash}) transaction_result_response = self.cmd.cmdWallet.txresult(conf) self.assertFalse(transaction_result_response.get('error', False)) # check the stepLimit in the confirmed tx confirmed_transaction = self.cmd.cmdWallet.txbyhash(conf) self.assertTrue(confirmed_transaction['result']['stepLimit'], '0x3000000') # use the stepLimit in the json file, with keystore args["keyStore"] = os.path.join(TEST_UTIL_DIRECTORY, 'test_keystore') conf = self.cmd.cmdWallet.get_icon_conf(command='sendtx', args=args) response = self.tx_command("sendtx", conf=conf, password='******') self.assertEqual(response.get('error', False), False) # check result tx_hash = response['result'] conf = self.cmd.cmdWallet.get_icon_conf('txresult', {'hash': tx_hash}) transaction_result_response = self.cmd.cmdWallet.txresult(conf) self.assertFalse(transaction_result_response.get('error', False)) # check the stepLimit in the confirmed tx confirmed_transaction = self.cmd.cmdWallet.txbyhash(conf) self.assertTrue(confirmed_transaction['result']['stepLimit'], '0x3000000') # no stepLimit in the json file, invoke estimateStep send_json_path = os.path.join(TEST_UTIL_DIRECTORY, 'send_wo_steplimit.json') args = {"json_file": send_json_path} conf = self.cmd.cmdWallet.get_icon_conf(command='sendtx', args=args) response = self.tx_command("sendtx", conf=conf) self.assertEqual(response.get('error', False), False) # check result tx_hash = response['result'] conf = self.cmd.cmdWallet.get_icon_conf('txresult', {'hash': tx_hash}) transaction_result_response = self.cmd.cmdWallet.txresult(conf) self.assertFalse(transaction_result_response.get('error', False)) # no stepLimit, with keystore send_json_path = os.path.join(TEST_UTIL_DIRECTORY, 'send_wo_steplimit.json') args = { "json_file": send_json_path, "keyStore": os.path.join(TEST_UTIL_DIRECTORY, 'test_keystore') } conf = self.cmd.cmdWallet.get_icon_conf(command='sendtx', args=args) response = self.tx_command("sendtx", conf=conf, password='******') self.assertEqual(response.get('error', False), False) # check result tx_hash = response['result'] conf = self.cmd.cmdWallet.get_icon_conf('txresult', {'hash': tx_hash}) transaction_result_response = self.cmd.cmdWallet.txresult(conf) self.assertFalse(transaction_result_response.get('error', False)) # use the stepLimit specified in the command line argument args = {"stepLimit": "0x1", "json_file": send_json_path} conf = self.cmd.cmdScore.get_icon_conf(command='sendtx', args=args) response = self.tx_command("sendtx", conf=conf) self.assertIsInstance(response.get('error', False), dict) # use the stepLimit in the config file tbears_cli_config_step_set_path = os.path.join( TEST_UTIL_DIRECTORY, 'test_tbears_cli_config_step_set.json') args = { "config": tbears_cli_config_step_set_path, "json_file": send_json_path } conf = self.cmd.cmdScore.get_icon_conf(command='sendtx', args=args) response = self.tx_command("sendtx", conf=conf) self.assertIsInstance(response.get('error', False), dict)