def _check_deploy(conf: dict, password: str = None): """Check keystore presence, and get password from user's terminal input (not validate password) password is an optional parameter for unit tests purposes :param conf: command configuration :param password: password for unit tests (optional) :return: password for keystore file """ # check if keystore exist. if exist, get password from user input if not conf['keyStore']: if not is_icon_address_valid(conf['from']): raise TBearsCommandException( f"You entered invalid 'from' address '{conf['from']}") else: if not password: password = getpass.getpass("Input your keystore password: "******"You entered invalid 'to' address '{conf['to']}") # check project directory check_project(conf.get('project', "")) return password
def start(self, conf: dict): """ Start tbears service Start iconservice, tbears_block_manager, iconrpcserver :param conf: start command configuration """ if self.is_service_running(): raise TBearsCommandException(f"tbears service was started already") if self.is_port_available(conf) is False: raise TBearsCommandException( f"port {conf['port']} already in use. use other port.") # write temporary configuration file temp_conf = './temp_conf.json' with open(temp_conf, mode='w') as file: file.write(json.dumps(conf)) # run iconservice self._start_iconservice(conf, temp_conf) # start tbears_block_manager self._start_blockmanager(conf) # start iconrpcserver self._start_iconrpcserver(conf, temp_conf) time.sleep(3) # remove temporary configuration file os.remove(temp_conf) # write server configuration self.write_server_conf(conf) print(f'Started tbears service successfully')
def check_project(project_path: str) -> int: if os.path.isdir(project_path): # there is no __init__.py if not os.path.exists(f"{project_path}/__init__.py"): raise TBearsCommandException( f'There is no __init__.py in project directory') # there is no package.json if not os.path.exists(f"{project_path}/package.json"): raise TBearsCommandException( f'There is no package.json in project directory') with open(f"{project_path}/package.json", mode='r') as file: try: package: dict = json.load(file) except Exception as e: raise TBearsCommandException( f'package.json has wrong format. {e}') # wrong package.json file if 'version' not in package or 'main_file' not in package or 'main_score' not in package: raise TBearsCommandException(f'package.json has wrong format.') # there is no main_file if not os.path.exists(f"{project_path}/{package['main_file']}.py"): raise TBearsCommandException( f"There is no main_file '{project_path}/{package['main_file']}.py'" ) return 0
def block(self, conf): """Query block with given parameter(height or hash) :param conf: block command configuration :return: result of query """ uri, version = uri_parser(conf['uri']) icon_service, response = IconService(HTTPProvider(uri, version)), None hash, number = conf.get('hash'), conf.get('number') if hash is not None and number is not None: raise TBearsCommandException( "Only one of id and number can be passed.") if hash is not None: response = icon_service.get_block(hash, True, BLOCK_0_3_VERSION) if number is not None: response = icon_service.get_block(convert_hex_str_to_int(number), True, BLOCK_0_3_VERSION) if response is None: raise TBearsCommandException( "You have to specify block height or block hash") if "error" in response: print(json.dumps(response, indent=4)) else: print(f"block info : {json.dumps(response, indent=4)}") return response
def _check_sendtx(conf: dict, password: str = None): if conf.get('keyStore', None): if not os.path.exists(conf['keyStore']): raise TBearsCommandException(f'There is no keystore file {conf["keyStore"]}') if not password: password = getpass.getpass("Input your keystore password: "******"from"]}') return password
def _check_keystore(password: str): if not password: password = getpass.getpass("Input your keystore password: "******"Retype your keystore password: "******"Sorry, passwords do not match. Failed to make keystore file") if not validate_password(password): raise TBearsCommandException("Password must be at least 8 characters long including alphabet, number, " "and special character.") return password
def _check_transfer(conf: dict, password: str = None): if not is_icon_address_valid(conf['to']): raise TBearsCommandException(f'You entered invalid address') # value must be a integer value if conf['value'] != float(int(conf['value'])): raise TBearsCommandException( f'You entered invalid value {conf["value"]}') if conf.get('keyStore', None): if not password: password = getpass.getpass("input your keystore password: ") return password
def _check_transfer(conf: dict, password: str = None): if not is_icon_address_valid(conf['to']): raise TBearsCommandException(f'You entered invalid address') if conf['to'] == keystore_test1['address']: uri: str = conf['uri'] index = uri.find('127.0.0.1') if index == -1 or uri[index + len('127.0.0.1')] != ':': raise TBearsCommandException(f'Do not transfer to "test1" account') if conf.get('keyStore', None): if not password: password = getpass.getpass("Input your keystore password: ") return password
def clear(_conf: dict): """Clear all SCORE deployed on tbears service :param _conf: clear command configuration """ # referenced data's path is /tmp/.tbears.env (temporary config data) score_dir_info = CommandServer.get_server_conf() if score_dir_info is None: raise TBearsDeleteTreeException("Already clean.") if CommandServer.is_service_running(): raise TBearsCommandException( f'You must stop tbears service to clear SCORE') # delete whole score data try: if os.path.exists(score_dir_info['scoreRootPath']): shutil.rmtree(score_dir_info['scoreRootPath']) if os.path.exists(score_dir_info['stateDbRootPath']): shutil.rmtree(score_dir_info['stateDbRootPath']) CommandServer._delete_server_conf() except (PermissionError, NotADirectoryError) as e: raise TBearsDeleteTreeException(f"Can't delete SCORE files. {e}") # delete temporary config data (path: /tmp/.tbears.env) CommandServer._delete_server_conf() print(f"Cleared SCORE deployed on tbears successfully")
def _check_keystore(password: str): if not password: password = getpass.getpass("input your keystore password: "******"Password must be at least 8 characters long including alphabet, number, " "and special character.") return password
def run(self, args): if not hasattr(self, args.command): raise TBearsCommandException(f"Invalid command {args.command}") # load configurations conf = self.get_icon_conf(args.command, args=vars(args)) # run command return getattr(self, args.command)(conf)
def run(self, args): if not hasattr(self, args.command): raise TBearsCommandException(f"Invalid command {args.command}") user_input = vars(args) conf = self.get_icon_conf(args.command, args=user_input) # run command return getattr(self, args.command)(conf)
def run(self, args): if not hasattr(self, args.command): raise TBearsCommandException(f"Invalid command {args.command}") user_input = vars(args) conf = self.get_icon_conf(args.command, args=user_input) Logger.info(f"Run '{args.command}' command with config: {conf}", TBEARS_CLI_TAG) # run command return getattr(self, args.command)(conf)
def sync_mainnet(self, _conf: dict): """ Sync revision and governance SCORE with the mainnet :param conf: :return: None """ if self.get_server_conf() is not None or self.is_service_running(): raise TBearsCommandException( f'You must stop T-Bears service and clear SCORE to run sync_mainnet command' ) # copy mainnet DB dir_path = os.path.abspath(os.path.dirname(__file__)) path = os.path.join(dir_path, f"../data/mainnet.tar.gz") subprocess.run(['tar', 'xzvf', path], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) print( f'Synchronized successfully revision and governance SCORE with the mainnet' )
def check_project(project_path: str) -> int: if os.path.isdir(project_path): # there is no __init__.py if not os.path.exists(f"{project_path}/__init__.py"): raise TBearsCommandException( f'There is no __init__.py in project directory') # there is no package.json if not os.path.exists(f"{project_path}/package.json"): raise TBearsCommandException( f'There is no package.json in project directory') with open(f"{project_path}/package.json", mode='r') as file: try: package: dict = json.load(file) except Exception as e: raise TBearsCommandException( f'package.json has wrong format. {e}') # wrong package.json file if 'version' not in package or 'main_score' not in package: raise TBearsCommandException(f'package.json has wrong format.') # check the validity of main_module main_module: str = package.get('main_module') if not isinstance(main_module, str): try: # this will be deprecated soon main_module: str = package['main_file'] except KeyError: raise TBearsCommandException( f'package.json should have main_module field.') if main_module.startswith('.') or main_module.find('/') != -1: raise TBearsCommandException( f'Invalid main_module field: {main_module}') main_file = main_module.replace('.', '/') + '.py' if not os.path.exists(f"{project_path}/{main_file}"): raise TBearsCommandException( f"There is no '{project_path}/{main_file}'") return 0
def _check_deploy(conf: dict, password: str = None): """Check keystore presence, and get password from user's terminal input(not validate password) the reason why receive password as parameter is for unit tests :param conf: command configuration :param password: password for unit tests(optional) :return: password for keystore file """ if not os.path.isdir(conf['project']): raise TBearsCommandException( f'There is no project directory.({conf["project"]})') if conf['contentType'] == 'zip': if conf.get('keyStore', None) is None: raise TBearsCommandException( f'If you want to deploy SCORE to ICON node, set --key-store option or ' f'write "keyStore" value in configuration file.') else: uri: str = conf.get('uri', "") if uri and uri.find('127.0.0.1') == -1: raise TBearsCommandException( f"TBears does not support deploying tbears SCORE to remote" ) # check if keystore exist. if exist, get password from user input if not conf['keyStore']: if not is_icon_address_valid(conf['from']): raise TBearsCommandException( f"You entered invalid 'from' address '{conf['from']}") else: if not password: password = getpass.getpass("input your keystore password: "******"You entered invalid 'to' address '{conf['to']}") return password
def _check_init(conf: dict): if conf['project'] == conf['score_class']: raise TBearsCommandException( f'<project> and <score_class> must be different.')
def deploy(self, conf: dict) -> dict: """Deploy SCORE on the server. :param conf: deploy command configuration """ if conf['contentType'] == 'tbears' and not CommandServer.is_service_running( ): raise TBearsCommandException(f'Start tbears service first') # check keystore, and get password from user's terminal input password = conf.get('password', None) password = self._check_deploy(conf, password) step_limit = conf.get('stepLimit', "0x1234000") if conf['mode'] == 'install': score_address = f'cx{"0"*40}' else: score_address = conf['to'] if conf['contentType'] == 'zip': content_type = "application/zip" # make zip and convert to hexadecimal string data(start with 0x) and return content = IconJsonrpc.gen_deploy_data_content(conf['project']) else: content_type = "application/tbears" content = os.path.abspath(conf['project']) # make IconJsonrpc instance which is used for making request(with signature) if conf['keyStore']: deploy = IconJsonrpc.from_key_store(keystore=conf['keyStore'], password=password) else: deploy = IconJsonrpc.from_string(from_=conf['from']) # make JSON-RPC 2.0 request standard format request = deploy.sendTransaction(to=score_address, nid=conf['nid'], step_limit=step_limit, data_type="deploy", data=IconJsonrpc.gen_deploy_data( params=conf.get( 'scoreParams', {}), content_type=content_type, content=content)) # send request to rpcserver icon_client = IconClient(conf['uri']) response = icon_client.send(request) if 'error' in response: print('Got an error response') print(json.dumps(response, indent=4)) else: print('Send deploy request successfully.') tx_hash = response['result'] print( f'If you want to check SCORE deployed successfully, execute txresult command' ) print(f"transaction hash: {tx_hash}") return response