web3j采用call方式查询智能合约执行结果
?
?
以太坊在調(diào)用智能合約中的函數(shù)時(shí),即使交易成功發(fā)布到區(qū)塊鏈上,但是如果合約參數(shù)檢查出錯(cuò),交易執(zhí)行會(huì)失敗,這個(gè)時(shí)候調(diào)用端仍然能夠查詢到交易被打包,但是交易執(zhí)行結(jié)果跟期望的會(huì)不相符。
假設(shè)一個(gè)智能合約中有一個(gè)transfer函數(shù):
function transfer(address to, uint256 val) public view returns(bool) {require (msg.sender==owner);//only contract owner can call this functionassert (val>0 && this.balance>=val);to.transfer(val);Award(to,val);return true;}transfer函數(shù)中用require檢查了參數(shù),如果調(diào)用者不是合約發(fā)布者owner,或者合約的賬戶余額小于轉(zhuǎn)賬額度,都會(huì)拋出異常,導(dǎo)致交易區(qū)塊鏈上回滾。
現(xiàn)在我這測(cè)試鏈上contract合約是由賬戶1發(fā)布的。如果讓賬戶0來(lái)調(diào)用該合約給賬戶2轉(zhuǎn)賬10 ether,看一下區(qū)塊鏈會(huì)發(fā)生什么情況:
> contract.transfer.sendTransaction(eth.accounts[2],web3.toWei(10,"ether"),{from:eth.coinbase}) INFO [08-15|17:16:11.230] Submitted transaction fullhash=0x6b87baddbf25edd4bf0d08a47a6f30a7811aba80ec4b1be248369b61983aece4 recipient=0xC14E589990F7e6F7cD4beDdb073716f66bbd254b "0x6b87baddbf25edd4bf0d08a47a6f30a7811aba80ec4b1be248369b61983aece4" INFO [08-15|17:16:11.230] evm run error err="invalid opcode 0xfd" INFO [08-15|17:16:11.230] VM returned with error err="invalid opcode 0xfd" > miner.start() INFO [08-15|17:16:21.585] Updated mining threads threads=0 INFO [08-15|17:16:21.585] Transaction pool price threshold updated price=12000000000000 INFO [08-15|17:16:21.585] Starting mining operation INFO [08-15|17:16:23.732]查詢交易:
> eth.getTransaction("0x6b87baddbf25edd4bf0d08a47a6f30a7811aba80ec4b1be248369b61983aece4") {blockHash: "0x6b0b9d2afc7a575d98cd9ba5a6f8573cb63a39dd5213c2b91fc6efb1ce5d42cb",blockNumber: 8,from: "0xe0d268886b753fd1778b3698956726c3dbf5d9a4",gas: 90000,gasPrice: 100000000000,hash: "0x6b87baddbf25edd4bf0d08a47a6f30a7811aba80ec4b1be248369b61983aece4",input: "0xa9059cbb00000000000000000000000041111c21df363759fa47fabf530508369c0463190000000000000000000000000000000000000000000000008ac7230489e80000",nonce: 4,r: "0x1c0b64699e19f83af21119c47aa553bfcd74d3bffbf59f6ac8c7bef351efab5f",s: "0x6b3dffc583e4a33ccf4edd6c0a766d8f0b29c8ee98ff8688e2722924a82569ec",to: "0xc14e589990f7e6f7cd4beddb073716f66bbd254b",transactionIndex: 0,v: "0x10a",value: 0 } >可以看到交易被打包到高度為8的區(qū)塊中了,但是賬戶2收到10 ether了沒(méi)有?查詢賬戶2余額:
> eth.getBalance(eth.accounts[2]) 0可以看到合約交易雖然被打包,但是合約函數(shù)執(zhí)行結(jié)果沒(méi)效果。這個(gè)時(shí)候程序端是很難監(jiān)控到合約執(zhí)行效果的。由于合約函數(shù)調(diào)用時(shí)參數(shù)錯(cuò)誤導(dǎo)致合約執(zhí)行失敗,區(qū)塊鏈?zhǔn)遣粫?huì)返回錯(cuò)誤給調(diào)用端的。可以采用call調(diào)用的方式來(lái)查詢合約函數(shù)執(zhí)行結(jié)果:
> contract.transfer(eth.accounts[1],web3.toWei(10,"ether"),{from:eth.coinbase}) INFO [08-16|11:06:50.363] evm run error err="invalid opcode 0xfd" INFO [08-16|11:06:50.363] VM returned with error err="invalid opcode 0xfd" false > contract.transfer(eth.accounts[1],web3.toWei(10,"ether"),{from:eth.accounts[1]}) true >采用call查詢智能合約的transfer函數(shù)執(zhí)行能不能成功,第一次使用eth.coinbase來(lái)調(diào)用合約,發(fā)現(xiàn)返回false。第二次使用合約的發(fā)布賬戶eth.accounts[1]來(lái)調(diào)用,這回返回true,說(shuō)明這樣能夠調(diào)用成功。使用call方式只是查詢區(qū)塊鏈,但是并不會(huì)向區(qū)塊鏈提交交易。
web3j里面實(shí)現(xiàn)call查詢方式是:
public boolean querryTransfer(String to, BigInteger val, String from, String contractAddress) throws Exception{List<Type> inputParameters = new ArrayList<>();inputParameters.add(new Address(to));inputParameters.add(new Uint256(val));Function function = new Function("transfer",inputParameters,Collections.<TypeReference<?>>emptyList());String encodedFunction = FunctionEncoder.encode(function);org.web3j.protocol.core.methods.response.EthCall response = ethClient.ethCall(Transaction.createEthCallTransaction(from, contractAddress, encodedFunction),DefaultBlockParameterName.LATEST).sendAsync().get();if(response.getValue().equals("0x"))return false;return true;}當(dāng)函數(shù)返回false,說(shuō)明合約函數(shù)調(diào)用會(huì)失敗,這個(gè)時(shí)候需要檢查相關(guān)參數(shù)。當(dāng)函數(shù)返回true,則可以調(diào)用正式的合約函數(shù)調(diào)用去向區(qū)塊鏈發(fā)起合約調(diào)用的交易。
總結(jié)
以上是生活随笔為你收集整理的web3j采用call方式查询智能合约执行结果的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java rails orm_rails
- 下一篇: 【收藏】window、mac、linux