def call(self, to_address, contract_abi, fn_name, args=None): cmd = "call" if to_address != "": common.check_and_format_address(to_address) if self.client_account is None: self.load_default_account() functiondata = encode_transaction_data(fn_name, contract_abi, None, args) callmap = dict() callmap["data"] = functiondata callmap["from"] = self.client_account.address callmap["to"] = to_address callmap["value"] = 0 # send transaction to the given group params = [client_config.groupid, callmap] # 发送 response = self.common_request(cmd, params) if "output" in response.keys(): outputdata = response["output"] # 取得方法的abi,签名,参数 和返回类型,进行call返回值的解析 fn_abi, fn_selector, fn_arguments = get_function_info( fn_name, contract_abi, None, args, None, ) # print("fn_selector",fn_selector) # print("fn_arguments",fn_arguments) fn_output_types = get_fn_abi_types_single(fn_abi, "outputs") # print("output types str:", fn_output_types) decoderesult = decode_single(fn_output_types, decode_hex(outputdata)) return decoderesult return response
def sendRawTransaction(self, to_address, contract_abi, fn_name, args=None, bin_data=None, gasPrice=30000000, packet_type=ChannelPack.TYPE_RPC): cmd = "sendRawTransaction" if to_address != "": common.check_and_format_address(to_address) # 第三个参数是方法的abi,可以传入None,encode_transaction_data做了修改,支持通过方法+参数在整个abi里找到对应的方法abi来编码 if bin_data is None: functiondata = encode_transaction_data(fn_name, contract_abi, None, args) # the args is None elif args is None: functiondata = bin_data # deploy with params else: fn_data = get_aligned_function_data(contract_abi, None, args) functiondata = bin_data + fn_data[2:] if to_address is not None and len(to_address) > 0: from eth_utils import to_checksum_address to_address = to_checksum_address(to_address) # load default account if not set .notice: account only use for # sign transaction for sendRawTransa# if self.client_account is None: self.load_default_account() # 填写一个bcos transaction 的 mapping import random txmap = dict() txmap["randomid"] = random.randint(0, 1000000000) # 测试用 todo:改为随机数 txmap["gasPrice"] = gasPrice txmap["gasLimit"] = gasPrice txmap["blockLimit"] = self.getBlockLimit() # 501 # 测试用,todo:从链上查一下 txmap["to"] = to_address txmap["value"] = 0 txmap["data"] = functiondata txmap["fiscoChainId"] = self.fiscoChainId txmap["groupId"] = self.groupid txmap["extraData"] = "" #print("\n>>>>functiondata ",functiondata) sign = SignTx() sign.crypto_type = client_config.crypto_type # 关键流程:对交易签名,重构后全部统一到 SignTx 类(client/signtransaction.py)完成 sign.gm_account = self.gm_account sign.ecdsa_account = self.ecdsa_account signed_result = sign.sign_transaction(txmap) #print("@@@@@rawTransaction : ",encode_hex(signedTxResult.rawTransaction)) # signedTxResult.rawTransaction是二进制的,要放到rpc接口里要encode下 params = [self.groupid, encode_hex(signed_result.rawTransaction)] result = self.common_request(cmd, params, packet_type) return result
def sendRawTransaction(self, to_address, contract_abi, fn_name, args=None, bin_data=None, gasPrice=30000000, packet_type=ChannelPack.TYPE_RPC): cmd = "sendRawTransaction" if to_address != "": common.check_and_format_address(to_address) # 第三个参数是方法的abi,可以传入None,encode_transaction_data做了修改,支持通过方法+参数在整个abi里找到对应的方法abi来编码 if bin_data is None: functiondata = encode_transaction_data(fn_name, contract_abi, None, args) # the args is None elif args is None: functiondata = bin_data # deploy with params else: fn_data = get_aligned_function_data(contract_abi, None, args) functiondata = bin_data + fn_data[2:] if to_address is not None and len(to_address) > 0: from eth_utils import to_checksum_address to_address = to_checksum_address(to_address) # load default account if not set .notice: account only use for # sign transaction for sendRawTransaction if self.client_account is None: self.load_default_account() # 填写一个bcos transaction 的 mapping import random txmap = dict() txmap["randomid"] = random.randint(0, 1000000000) # 测试用 todo:改为随机数 txmap["gasPrice"] = gasPrice txmap["gasLimit"] = gasPrice txmap["blockLimit"] = self.getBlockLimit() # 501 # 测试用,todo:从链上查一下 txmap["to"] = to_address txmap["value"] = 0 txmap["data"] = functiondata txmap["fiscoChainId"] = self.fiscoChainId txmap["groupId"] = self.groupid txmap["extraData"] = "" ''' from datatypes.bcostransactions import ( serializable_unsigned_transaction_from_dict, ) # 将mapping构建一个transaction对象,非必要,用来对照的 transaction = serializable_unsigned_transaction_from_dict(txmap) # 感受下transaction encode的原始数据 print(encode_hex(rlp.encode(transaction))) ''' # 实际上只需要用sign_transaction就可以获得rawTransaction的编码数据了,input :txmap,私钥 signedTxResult = Account.sign_transaction(txmap, self.client_account.privateKey) # signedTxResult.rawTransaction是二进制的,要放到rpc接口里要encode下 params = [self.groupid, encode_hex(signedTxResult.rawTransaction)] result = self.common_request(cmd, params, packet_type) return result
def revoke(self, table_name, account_address): """ revoke write permission to table_name from account_address related api: function remove(string table_name, string addr) public returns(int256); """ common.check_and_format_address(account_address) common.check_address_startwith_0x(account_address) fn_name = "remove" fn_args = [table_name, account_address] return self.client.send_transaction_getReceipt(fn_name, fn_args, self.gasPrice)
def grant(self, table_name, account_address): """ grant write permission of table_name to account_address related api: function insert(string table_name, string addr) public returns(int256); """ common.check_and_format_address(account_address) common.check_address_startwith_0x(account_address) fn_name = "insert" fn_args = [table_name, account_address] return self.client.send_transaction_getReceipt(fn_name, fn_args, self.gasPrice)
def call(self, to_address, contract_abi, fn_name, args=None): cmd = "call" if to_address != "": common.check_and_format_address(to_address) self.load_default_account() functiondata = encode_transaction_data(fn_name, contract_abi, None, args) callmap = dict() callmap["data"] = functiondata callmap["from"] = self.default_from_account_signer.get_keypair( ).address callmap["to"] = to_address callmap["value"] = 0 # send transaction to the given group params = [client_config.groupid, callmap] # 发送 response = self.common_request(cmd, params) #print("response : ",response) # check status if "status" in response.keys(): status = int(response["status"], 16) error_message = transaction_status_code.TransactionStatusCode.get_error_message( status) if error_message is not None: raise BcosException( "call error, error message: {}".format(error_message)) if "output" in response.keys(): outputdata = response["output"] # 取得方法的abi,签名,参数 和返回类型,进行call返回值的解析 fn_abi, fn_selector, fn_arguments = get_function_info( fn_name, contract_abi, None, args, None, ) # print("fn_selector",fn_selector) # print("fn_arguments",fn_arguments) #fn_output_types = get_fn_abi_types_single(fn_abi, "outputs") fn_output_types = get_abi_output_types(fn_abi) try: #decoderesult = decode_single(fn_output_types, decode_hex(outputdata)) #print("fn_output_types",fn_output_types) decoderesult = decode_abi(fn_output_types, decode_hex(outputdata)) return decoderesult except BaseException as e: return response return response
def register_cns(self, name, version, address, abi): """ register cns contract: (name, version)->address precompile api: insert(string,string,string,string) """ common.check_and_format_address(address) version = re.sub(r"\s+", "", version) common.print_info("INFO", "CNS version (strip space): {}".format(version)) # invalid version if len(version) > self._max_version_len: error_info = self.get_error_msg(self._version_exceeds) self.logger.error("register cns failed, error info: {}".format(error_info)) raise BcosException(error_info) # call insert function of CNS # function definition: insert(string,string,string,string) fn_name = "insert" fn_args = [name, version, address, json.dumps(abi)] return self.client.send_transaction_getReceipt(fn_name, fn_args, self.gasPrice)
def getCode(self, address): cmd = "getCode" fmt_addr = common.check_and_format_address(address) params = [self.groupid, fmt_addr] return self.common_request(cmd, params)