Solidity
呼叫非視圖函式時如何獲取返回值?
我在下面寫了一個簡單的契約,其中儲存了每個 ID 的所有問卷結果。
contract answer{ mapping(address => mapping(string => bool)) voters; struct qList { uint count; //The number of respondents mapping(address => mapping(uint => uint)) answer; } mapping(string => qList) questionnaires; function vote(string ID, uint qNum, uint ans) returns (bool) { if(voters[msg.sender][ID]) throw; voters[msg.sender][ID] = true; questionnaires[ID].count += 1; questionnaires[ID].answer[msg.sender][qNum] = ans; return true; } function getNumResult(string ID) constant returns (uint res) { return questionnaires[ID].count; } }
該函式
vote
可以被成功呼叫和探勘,但是我無法獲取vote
.如果有人會建議導致此問題的原因和解決方案以獲取帶參數的函式的返回值,我們將不勝感激。
概括
當我通過
geth
控制台執行程式碼時,您的程式碼會按預期執行。如果它對您不起作用,請嘗試增加您在交易中發送的氣體。正如
@Taylor Gerring
他在回答中所說,您可能無法從您的vote()
函式中獲得結果,但您的程式碼似乎可以正常工作。如果你想要你的
vote()
函式的結果,在你的例子中是檢查一個人之前是否投票過,你的數據中已經有了這個voters
數據。細節
我已經獲取了您的原始碼,只是將類名從更改
answer
為Answer
,並將您的評論從//
更改為/*...*/
:contract Answer { mapping(address => mapping(string => bool)) voters; struct qList { uint count; /* The number of respondents */ mapping(address => mapping(uint => uint)) answer; } mapping(string => qList) questionnaires; function vote(string ID, uint qNum, uint ans) returns (bool) { if (voters[msg.sender][ID]) throw; voters[msg.sender][ID] = true; questionnaires[ID].count += 1; questionnaires[ID].answer[msg.sender][qNum] = ans; return true; } function getNumResult(string ID) constant returns (uint res) { return questionnaires[ID].count; } }
我已經從程式碼中刪除了 CR-LF 並折疊了空格,並在中執行了以下語句
geth
:> var answerSource='contract Answer { mapping(address => mapping(string => bool)) voters; struct qList { uint count; /* The number of respondents */ mapping(address => mapping(uint => uint)) answer; } mapping(string => qList) questionnaires; function vote(string ID, uint qNum, uint ans) returns (bool) { if(voters[msg.sender][ID]) throw; voters[msg.sender][ID] = true; questionnaires[ID].count += 1; questionnaires[ID].answer[msg.sender][qNum] = ans; return true; } function getNumResult(string ID) constant returns (uint res) { return questionnaires[ID].count; }}' undefined
然後我編譯了您的程式碼並將其插入到我的開發區塊鏈中:
> var answerCompiled = web3.eth.compile.solidity(answerSource); undefined > var answerContract = web3.eth.contract(answerCompiled.Answer.info.abiDefinition); undefined > var answer = answerContract.new({ from:web3.eth.accounts[0], data: answerCompiled.Answer.code, gas: 2000000}, function(e, contract) { if (!e) { if(!contract.address) { console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined..."); } else { console.log("Contract mined! Address: " + contract.address); console.log(contract); } } }) Contract transaction send: TransactionHash: 0x5b5eb3c6d2a4b43eff4444b71b762911ddc72e239d1d495b6bec7b2e6a738df0 waiting to be mined...
我等待合約被探勘並收到以下消息:
Contract mined! Address: 0xe51ac93e4c28206f0f0296e5b6d66daf0a917bc3 [object Object]
檢查
getNumResult()
:> answer.getNumResult("idOne") 0
投票:
> answer.vote("idOne", 1, 1, eth.accounts[0], { from:web3.eth.accounts[0], data: answerCompiled.Answer.code, gas: 1000000 }); "0xfcbf47472733c0922552aa617fc7cb1226c346edc022fbe09ea521dfb75f7699"
等待交易被探勘並檢查交易:
> eth.getTransaction("0xfcbf47472733c0922552aa617fc7cb1226c346edc022fbe09ea521dfb75f7699") { ... blockNumber: 6567, ... }
檢查
getNumResult()
:> answer.getNumResult("idOne") 1
使用不同的 ID 發送另一個投票:
> answer.vote("idTwo", 2, 1, eth.accounts[0], { from:web3.eth.accounts[0], data: answerCompiled.Answer.code, gas: 1000000 });
檢查結果:
> answer.getNumResult("idTwo") 1
用相同的 ID 從同一個帳戶發送另一個投票:
> answer.vote("idOne", 2, 1, eth.accounts[0], { from:web3.eth.accounts[0], data: answerCompiled.Answer.code, gas: 1000000 }); "0xbbf9db6eb7c02571948002f56e3a7c56b6c7f55c2a4bbc70a244bb2afbf44e1f"
我注意到以下錯誤:
PC 00000366: JUMP GAS: 976744 COST: 8 ERROR: invalid jump destination (PUSH1) 2
throw
如果同一個ID是從同一個賬戶投票的,那麼上面的錯誤肯定是由你程式碼中的語句產生的:if (voters[msg.sender][ID]) throw;
然後,我從我的第二個帳戶發送了另一票:
> answer.vote("idOne", 2, 1, eth.accounts[1], { from:web3.eth.accounts[1], data: answerCompiled.Answer.code, gas: 1000000 });
結果按預期更新:
> answer.getNumResult("idOne") 2