Solidity
Web3 常量方法呼叫的結果不一致
部署了本地私有乙太坊環境。在嘗試呼叫solidity合約的常量方法時,結果不一致。
有時會返回結果,但大多數情況下不會。
當我嘗試從 geth 命令行獲取數據時,每次都能成功列出結果。
在下面的 Nodejs 程式碼中,創建了一個 20 次迭代的循環來獲取資產價格。有時 10-15 次正確返回結果,並且很多次在沒有找到任何迭代結果,而是說 0。
契約
pragma solidity ^0.4.9; contract Asset { address public owner; struct Asset { string title; string description; uint assetTime; uint price; } Asset[] public assets; event LogAssetAdded(address indexed fromAddress, string description); // add asset function addAsset(string description1, string title1, uint price1,uint assetTime1) returns (uint, string, string, uint, uint) { uint assetID = assets.length++; Asset o = assets[assetID]; o.description = description1; o.assetTime=assetTime1; o.title = title1; o.price = price1; LogAssetAdded(msg.sender, description1); return (assetID, assets[assetID].description, assets[assetID].title, assets[assetID].price, assets[assetID].assetTime); } //return the number of assets function assetCount() public constant returns(uint) { uint assetCount =assets.length; return(assetCount); } function getAssetPrice(uint assetID) public constant returns(uint) { return assets[assetID].price; } function getDefAssetPrice() public constant returns(uint) { return assets[assets.length-1].price; } function getDefAssetTitle() public constant returns(string) { return assets[assets.length-1].title; } function getDefAssetTime() public constant returns(uint) { return assets[assets.length-1].assetTime; } }
NodeJs 客戶端程式碼
const rpcURL = 'http://localhost:9081' var Web3 = require('web3'); var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:9081")); const fs = require("fs"); let abi ='<<Apply ABI>>'; let bytecode = '<<Apply Bytecode >>' let gasEstimate = web3.eth.estimateGas({data: bytecode}); let assetContract = web3.eth.contract(JSON.parse(abi)); const account = '<<Provide from account>>'; var contractAddress = '<<Provide Contract Address>>'; var ctr1 = 0; var contract = assetContract.at(contractAddress); // Method to create asset function addAsset(){ contract.addAsset.sendTransaction("Asset Description", " Asset Title", 41202, 41203, {from: account, gas: 400000} , function(err, result){ if(err){ console.log('Error '+ err); } else{ console.log('Transaction Hash: '+ result); getAssetPrice(); } }); } // Method to fetch asset price function getAssetPrice(){ for(var i=0;i<20;i++){ contract.getAssetPrice(0, (error, result) => { if (!error && result>0) { ctr1++; console.log(ctr1 +": getAssetPrice: "+ result); } if (!error){ console.log("Error occurred: "+ error); } }); } addAsset(); //getAssetPrice()
依賴項
"web3": "^0.19", "solc": "^0.4.9"
格特版
v1.9.0 windows-amd64, go1.10.3
Geth 實例命令
geth --mine --minerthreads=1 --datadir D:/Ethereum/env-II/data/node1 --networkid 4224 --nodiscover --rpc --rpcport "9081" --port "30301" --rpccorsdomain "*" --nat "any" --rpcapi eth,web3,personal,net,miner --unlock 0 --password "D:/Ethereum/env-II/pwd.txt" --rpcaddr 0.0.0.0 --verbosity 2 console
Geth 命令行結果
> var assetContractRef = eth.contract('<<Contract abi>>'); > var assetContract = assetContractRef.at('<<Contract address>>') > assetContract.getAssetPrice(1); > 41202
使用 Call 呼叫的結果
Option 1: contract.getAssetPrice(0).call((error, result) => { TypeError: contract.getCallPrice(...).call is not a function Option 2: contract.getAssetPrice.call(0, (error, result) => { Faced same result i.e. inconsistent output.
筆記
我已經嘗試過這種實現,使用 Web3 1.0.0-beta.52 以及稍微修改的 nodejs 程式碼,即特定於 web3 1.0.0 簽名,但面臨同樣不一致的結果。如果需要,也可以共享該版本的 Nodejs 程式碼。
您可能希望
.call()
在呼叫常量(視圖)方法時使用。查看 Web3js 文件的此頁面以熟悉:https ://web3js.readthedocs.io/en/1.0/web3-eth-contract.html#methods-mymethod-call乍一看,我認為您需要更改的只是這一行:
contract.getAssetPrice(0, (error, result) => {
對此:
contract.getAssetPrice(0).call((error, result) => {
您在一定時間內多次發送請求。您的結果可能是由於 TCP 連接造成的。您正在使用
http
,嘗試使用websocket
作為提供者。var web3 = new Web3(new Web3.providers.WebsocketProvider("http://localhost:9081"));