def format_single_param(param, abitype): # 默认是string fmt_res = param # print(type(param)) if "int" in abitype or "int256" in abitype: if not isinstance(param, int): fmt_res = int(param, 10) if "address" in abitype: try: fmt_res = to_checksum_address(param) except ArgumentsError as e: raise ArgumentsError( ("ERROR >> covert {} to to_checksum_address failed," " exception: {}").format(param, e)) if "bytes" in abitype: try: fmt_res = bytes(param, "utf-8") except Exception as e: raise ArgumentsError( "ERROR >> parse {} to bytes failed, error info: {}".format( param, e)) if "bool" in abitype: # 有可能是string或已经是bool类型了,判断下 if isinstance(param, str): if "TRUE" == param.upper(): fmt_res = True elif "FALSE" == param.upper(): fmt_res = False else: raise ArgumentsError( "ERROR >> format bool type failed, WRONG param: {}".format( param)) return fmt_res
def exec_cmd_with_hash_param(self, cmd, params): """ execute cmd with one hash param """ if cmd not in RPCConsole.functions["one_hash"]: return # check_param common.check_param_num(params, 1, False) # check contract address if cmd == "getCode": try: if len(params) > 1: raise ArgumentsError( "{} must provide one param".format(cmd)) address = to_checksum_address(params[0]) self.exec_command(cmd, [address]) except Exception as e: raise ArgumentsError("invalid address: {}, info: {}".format( params[0], e)) else: if len(params) > 2: raise ArgumentsError( "{} must provide no more than one param".format(cmd)) # check hash common.check_hash(params[0]) result = self.exec_command(cmd, [params[0]]) if len(params) < 2 or result is None: return self.parse_output(cmd, params[1], result)
def check_param_num(args, expected, needEqual=False): """ check param num """ if needEqual is False: if len(args) < expected: raise ArgumentsError(("invalid arguments, expected num >= {}," "real num: {}").format(expected, len(args))) else: if len(args) != expected: raise ArgumentsError(("invalid arguments, expected num {}," "real num: {}").format(expected, len(args)))
def getSystemConfigByKey(self, key): if key not in BcosClient.sysconfig_keys: raise ArgumentsError("invalid system key, must be {}".format( BcosClient.sysconfig_keys)) cmd = "getSystemConfigByKey" params = [self.groupid, key] return self.common_request(cmd, params)
def format_args_by_function_abi(inputparams, inputabi): paramformatted = [] index = -1 if len(inputparams) != len(inputabi): raise ArgumentsError( ("Invalid Arguments {}, expected params size: {}," " inputted params size: {}".format(inputparams, len(inputabi), len(inputparams)))) for abi_item in inputabi: index += 1 param = inputparams[index] if param is None: continue if isinstance(param, Iterable) is False: paramformatted.append(param) continue abitype = abi_item["type"] (isarray, arraylen) = is_array_param(abitype) if isarray: # print("is Array") param = format_array_args_by_abi(param, abitype, arraylen) paramformatted.append(param) continue if '\'' in param: param = param.replace('\'', "") param = format_single_param(param, abitype) paramformatted.append(param) return paramformatted
def check_address_startwith_0x(address): """ check the address: must be starts with 0x """ if address.startswith("0x") is False: raise ArgumentsError( "invalid address {}, must be start with 0x".format(address))
def format_args_by_abi(inputparams, inputabi): try: paramformatted = [] index = -1 if len(inputparams) != len(inputabi): raise ArgumentsError( ("Invalid Arguments {}, expected params size: {}," " inputted params size: {}".format( inputparams, len(inputabi), len(inputparams)))) for input_item in inputabi: index += 1 param = inputparams[index] if param is None: continue if isinstance(param, Iterable) is False: paramformatted.append(param) continue if '\'' in param: param = param.replace('\'', "") if "int" in input_item["type"] or "int256" in input_item[ "type"]: print("&&&&&&", input_item["type"]) paramformatted.append(int(param, 10)) # paramformatted.append(param) continue if "address" in input_item["type"]: try: paramformatted.append(to_checksum_address(param)) except ArgumentsError as e: raise ArgumentsError(( "ERROR >> covert {} to to_checksum_address failed," " exception: {}").format(param, e)) continue if "bytes" in input_item["type"]: try: paramformatted.append(bytes(param, "utf-8")) except Exception as e: raise ArgumentsError( "ERROR >> parse {} to bytes failed, error info: {}" .format(param, e)) continue paramformatted.append(param) return paramformatted except Exception as e: raise BcosException(("inputparams illegal params: {}," "error info: {}").format(inputparams, e))
def check_nodeId(nodeId): """ check nodeId """ nodeId_len = 128 if len(nodeId) != nodeId_len: raise ArgumentsError("invalid nodeId, must be {} bytes".format(nodeId_len)) check_word(nodeId)
def check_word(word): """ check world """ result = re.findall(r'([0x]*[a-fA-F0-9]*)', word) if result[0] != word: raise ArgumentsError(("invalid input {}," " must be in 'a-f' or '0-9' or 'A-F'") .format(word))
def check_and_format_address(address): """ check address """ try: formatted_address = to_checksum_address(address) return formatted_address except Exception as e: raise ArgumentsError("invalid address {}, reason: {}" .format(address, e))
def exec_cmd_with_two_bool_param(self, cmd, params): """ execute cmd with two params """ if cmd not in RPCConsole.functions["two_bool"]: return # check param common.check_param_num(params, 1, False) if len(params) > 2: raise ArgumentsError("params must be no more than 2") self.exec_command(cmd, params)
def check_int_range(number_str, limit=max_block_number): """ check integer range """ try: if isinstance(number_str, int): return number_str number = 0 if isinstance(number_str, str): if number_str.startswith("0x"): number = int(number_str, 16) else: number = int(number_str) else: number = number_str if number > limit or number < 0: raise ArgumentsError(("invalid input: {}," " must between 0 and {}"). format(number_str, limit)) return number except Exception as e: raise ArgumentsError("invalid input:{}, error info: {}".format(number_str, e))
def format_array_args_by_abi(input_param, abitype, arraylen): # abi类型类似address[],string[],int256[] # 参数类似['0x111','0x2222'],[1,2,3],['aaa','bbb','ccc'] paramarray = parse_input_array_str(input_param) if arraylen > 0 and len(paramarray) != arraylen: raise ArgumentsError( "ERROR >> not match abi array size {}, params: {}".format( abitype, paramarray)) resarray = [] # print(paramarray) for param in paramarray: fmt_res = format_single_param(param, abitype) resarray.append(fmt_res) return resarray
def check_and_trans_to_bool(param): """ check bool """ if isinstance(param, bool): return param true_str = "true" false_str = "false" if isinstance(param, str): if param.lower() == true_str: return True if param.lower() == false_str: return False raise ArgumentsError(("invalid input: {}, " "must be true/True/false/False").format(param))
def exec_cmd_with_two_param(self, cmd, params): """ execute command with two params: """ if cmd not in RPCConsole.functions["two"]: return # check param common.check_param_num(params, 2, False) if len(params) > 3: raise ArgumentsError("{} : params must be no more than 3") index = common.check_int_range(params[1]) result = None # check param type if cmd == "getTransactionByBlockHashAndIndex": common.check_hash(params[0]) result = self.exec_command(cmd, [params[0], index]) if cmd == "getTransactionByBlockNumberAndIndex": number = common.check_int_range(params[0]) result = self.exec_command(cmd, [number, index]) self.parse_tx_and_receipt(result, cmd, params)
def format_tuple_args_by_abi(input_param, abitypestr): #print("format_tuple_args_by_abi param",input_param) abitype = parse_input_tuple_str(abitypestr) #print("format_tuple_args_by_abi abitype",abitype) paramtuple = parse_input_tuple_str(input_param) #print("format_tuple_args_by_abi tuple",paramtuple) arraylen = len(abitype) #print(arraylen) #print(len(paramtuple)) if arraylen > 0 and len(paramtuple) != arraylen: raise ArgumentsError( "ERROR >> not match abi array size {}, params: {}".format( abitype, paramtuple)) resarray = [] #print(paramtuple) i = 0 for param in paramtuple: fmt_res = format_single_param(param, abitype[i]) i += 1 resarray.append(fmt_res) #print("resarray",resarray) restuple = tuple(resarray) return restuple
def main(argv): try: usagemsg = usage(client_config) cmd, inputparams = parse_commands(argv) precompile = Precompile(cmd, inputparams, contracts_dir + "/precompile") # check cmd valid = check_cmd(cmd, validcmds) if valid is False: printusage(usagemsg, precompile) return # try to callback cns precompile precompile.call_cns() # try to callback consensus precompile precompile.call_consensus() # try to callback config precompile precompile.call_sysconfig_precompile() # try to callback permission precompile precompile.call_permission_precompile() # try to callback crud precompile precompile.call_crud_precompile() # try to callback rpc functions rpcConsole = RPCConsole(cmd, inputparams, contracts_dir) rpcConsole.executeRpcCommand() if cmd == 'showaccount': # must be 2 params common.check_param_num(inputparams, 2, True) name = inputparams[0] password = inputparams[1] keyfile = "{}/{}.keystore".format( client_config.account_keyfile_path, name) # the account doesn't exists if os.path.exists(keyfile) is False: raise BcosException("account {} doesn't exists".format(name)) print("show account : {}, keyfile:{} ,password {} ".format( name, keyfile, password)) try: with open(keyfile, "r") as dump_f: keytext = json.load(dump_f) stat = StatTool.begin() privkey = Account.decrypt(keytext, password) stat.done() print("decrypt use time : %.3f s" % (stat.time_used)) ac2 = Account.from_key(privkey) print("address:\t", ac2.address) print("privkey:\t", encode_hex(ac2.key)) print("pubkey :\t", ac2.publickey) print("\naccount store in file: [{}]".format(keyfile)) print("\n**** please remember your password !!! *****") except Exception as e: raise BcosException(("load account info for [{}] failed," " error info: {}!").format(name, e)) if cmd == 'newaccount': common.check_param_num(inputparams, 2, True) name = inputparams[0] max_account_len = 240 if len(name) > max_account_len: common.print_info( "WARNING", "account name should no more than {}".format( max_account_len)) sys.exit(1) password = inputparams[1] print("starting : {} {} ".format(name, password)) ac = Account.create(password) print("new address :\t", ac.address) print("new privkey :\t", encode_hex(ac.key)) print("new pubkey :\t", ac.publickey) stat = StatTool.begin() kf = Account.encrypt(ac.privateKey, password) stat.done() print("encrypt use time : %.3f s" % (stat.time_used)) keyfile = "{}/{}.keystore".format( client_config.account_keyfile_path, name) print("save to file : [{}]".format(keyfile)) forcewrite = False if not os.access(keyfile, os.F_OK): forcewrite = True else: # old file exist,move to backup file first if (len(inputparams) == 3 and inputparams[2] == "save"): forcewrite = True else: forcewrite = common.backup_file(keyfile) if forcewrite: with open(keyfile, "w") as dump_f: json.dump(kf, dump_f) dump_f.close() print(">>-------------------------------------------------------") print( "INFO >> read [{}] again after new account,address & keys in file:" .format(keyfile)) with open(keyfile, "r") as dump_f: keytext = json.load(dump_f) stat = StatTool.begin() privkey = Account.decrypt(keytext, password) stat.done() print("decrypt use time : %.3f s" % (stat.time_used)) ac2 = Account.from_key(privkey) print("address:\t", ac2.address) print("privkey:\t", encode_hex(ac2.key)) print("pubkey :\t", ac2.publickey) print("\naccount store in file: [{}]".format(keyfile)) print("\n**** please remember your password !!! *****") dump_f.close() # -------------------------------------------------------------------------------------------- # console cmd entity # -------------------------------------------------------------------------------------------- if cmd == "deploy": '''deploy abi bin file''' if len(inputparams) > 2: raise ArgumentsError( ("deploy failed, expected at most 2 params," " provided: {}").format(len(inputparams))) # must be at most 2 params common.check_param_num(inputparams, 1, False) contractname = inputparams[0].strip() gasPrice = 30000000 trans_client = transaction_common.TransactionCommon( "", contracts_dir, contractname) result = trans_client.send_transaction_getReceipt( None, None, gasPrice, True)[0] print("deploy result for [{}] is:\n {}".format( contractname, json.dumps(result, indent=4))) name = contractname address = result['contractAddress'] blocknum = int(result["blockNumber"], 16) ContractNote.save_contract_address(name, address) print("on block : {},address: {} ".format(blocknum, address)) if len(inputparams) == 2: if inputparams[1] == "save": ContractNote.save_address(name, address, blocknum) print("address save to file: ", client_config.contract_info_file) else: print('''\nNOTE : if want to save new address as last address for (call/sendtx)\nadd 'save' to cmdline and run again''' ) # -------------------------------------------------------------------------------------------- # console cmd entity # -------------------------------------------------------------------------------------------- if cmd == "call" or cmd == "sendtx": common.check_param_num(inputparams, 3) paramsname = ["contractname", "address", "func"] params = fill_params(inputparams, paramsname) contractname = params["contractname"] address = params["address"] if address == "last": address = ContractNote.get_last(contractname) if address is None: sys.exit("can not get last address for [{}],break;".format( contractname)) tx_client = transaction_common.TransactionCommon( address, contracts_dir, contractname) fn_name = params["func"] fn_args = inputparams[3:] print("INFO >> {} {} , address: {}, func: {}, args:{}".format( cmd, contractname, address, fn_name, fn_args)) if cmd == "call": result = tx_client.call_and_decode(fn_name, fn_args) print("INFO >> {} result: {}".format(cmd, result)) if cmd == "sendtx": receipt = tx_client.send_transaction_getReceipt( fn_name, fn_args)[0] data_parser = DatatypeParser(default_abi_file(contractname)) # 解析receipt里的log 和 相关的tx ,output print_receipt_logs_and_txoutput(tx_client, receipt, "", data_parser) # -------------------------------------------------------------------------------------------- # console cmd entity # -------------------------------------------------------------------------------------------- if cmd == "list": RPCConsole.print_rpc_usage() print( "--------------------------------------------------------------------" ) # -------------------------------------------------------------------------------------------- # console cmd entity # -------------------------------------------------------------------------------------------- if cmd == "txinput": contractname = inputparams[0] inputdata = inputparams[1] abi_path = default_abi_file(contractname) if os.path.isfile(abi_path) is False: raise BcosException( "execute {} failed for {} doesn't exist".format( cmd, abi_path)) try: dataParser = DatatypeParser(abi_path) # print(dataParser.func_abi_map_by_selector) result = dataParser.parse_transaction_input(inputdata) print("\nabifile : ", default_abi_file(contractname)) print("parse result: {}".format(result)) except Exception as e: raise BcosException("execute {} failed for reason: {}".format( cmd, e)) # -------------------------------------------------------------------------------------------- # console cmd entity # -------------------------------------------------------------------------------------------- if cmd == "checkaddr": address = inputparams[0] result = to_checksum_address(address) print("{} -->\n{}".format(address, result)) # -------------------------------------------------------------------------------------------- # console cmd entity # -------------------------------------------------------------------------------------------- if cmd == "usage": printusage(usagemsg, precompile) except TransactionException as e: common.print_error_msg(cmd, e) except PrecompileError as e: common.print_error_msg(cmd, e) except BcosError as e: common.print_error_msg(cmd, e) except CompileError as e: common.print_error_msg(cmd, e) except ArgumentsError as e: common.print_error_msg(cmd, e) except BcosException as e: common.print_error_msg(cmd, e)