Ich schreibe unten einen einfachen Vertrag, der alle Ergebnisse der Fragebögen für jede ID speichert.
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;
}
}
Die Funktion vote
kann erfolgreich aufgerufen und abgebaut werden, aber ich kann den Rückgabewert von nicht erhalten vote
.
Schätzen Sie es, wenn jemand die Ursache dafür und die Lösung empfehlen würde, um den Rückgabewert der Funktion mit Argumenten zu erhalten.
Ihr Code wird wie erwartet ausgeführt, wenn ich ihn über die Konsole ausführe geth
. Wenn es für Sie nicht funktioniert, versuchen Sie, das Gas zu erhöhen, das Sie mit Ihren Transaktionen senden.
Wie @Taylor Gerring
in seiner Antwort angegeben, können Sie die Ergebnisse Ihrer Funktion möglicherweise nicht abrufen vote()
, aber Ihr Code scheint in Ordnung zu sein.
Wenn Sie das Ergebnis Ihrer vote()
Funktion wollen, die in Ihrem Beispiel eine Überprüfung ist, ob eine Person schon einmal abgestimmt hat, haben Sie diese Daten bereits in Ihren voters
Daten.
Ich habe Ihren Quellcode genommen und nur den Klassennamen von answer
in geändert Answer
und Ihren Kommentar von //
in konvertiert /*...*/
:
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;
}
}
Ich habe das CR-LF aus dem Code entfernt und die Leerzeichen reduziert und die folgende Anweisung in ausgeführt 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
Ich habe dann Ihren Code kompiliert und in meine Dev-Blockchain eingefügt:
> 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...
Ich wartete darauf, dass der Vertrag abgebaut wurde und bekam folgende Meldung:
Contract mined! Address: 0xe51ac93e4c28206f0f0296e5b6d66daf0a917bc3
[object Object]
Geprüft getNumResult()
:
> answer.getNumResult("idOne")
0
Abgestimmt:
> answer.vote("idOne", 1, 1, eth.accounts[0], {
from:web3.eth.accounts[0],
data: answerCompiled.Answer.code,
gas: 1000000
});
"0xfcbf47472733c0922552aa617fc7cb1226c346edc022fbe09ea521dfb75f7699"
Wartete, bis die Transaktion abgebaut wurde, und überprüfte die Transaktion:
> eth.getTransaction("0xfcbf47472733c0922552aa617fc7cb1226c346edc022fbe09ea521dfb75f7699")
{
...
blockNumber: 6567,
...
}
Geprüft getNumResult()
:
> answer.getNumResult("idOne")
1
Eine weitere Stimme mit einer anderen ID gesendet:
> answer.vote("idTwo", 2, 1, eth.accounts[0], {
from:web3.eth.accounts[0],
data: answerCompiled.Answer.code,
gas: 1000000
});
Ergebnisse überprüft:
> answer.getNumResult("idTwo")
1
Eine weitere Stimme vom selben Konto mit derselben ID gesendet:
> answer.vote("idOne", 2, 1, eth.accounts[0], {
from:web3.eth.accounts[0],
data: answerCompiled.Answer.code,
gas: 1000000
});
"0xbbf9db6eb7c02571948002f56e3a7c56b6c7f55c2a4bbc70a244bb2afbf44e1f"
Und mir ist folgender Fehler aufgefallen:
PC 00000366: JUMP GAS: 976744 COST: 8 ERROR: invalid jump destination (PUSH1) 2
Der obige Fehler muss aus der Aussage in Ihrem Code generiert worden sein, throw
wenn dieselbe ID von demselben Konto gewählt wird:
if (voters[msg.sender][ID]) throw;
Ich habe dann eine weitere Stimme von meinem zweiten Konto gesendet:
> answer.vote("idOne", 2, 1, eth.accounts[1], {
from:web3.eth.accounts[1],
data: answerCompiled.Answer.code,
gas: 1000000
});
Und die Ergebnisse wurden wie erwartet aktualisiert:
> answer.getNumResult("idOne")
2
Es ist derzeit nicht möglich, Werte von Funktionen zurückzugeben, die die Blockchain verändern. Um einen Rückgabewert zu erhalten, können Sie Funktionen als "pure" oder "view" markieren .
Für zustandsändernde Funktionen ist die einzige Möglichkeit, Informationen „zurückzugeben“, die Verwendung von Solidity-Ereignissen, die als LOG-Opcodes in der Ethereum Virtual Machine zusammenfließen.
Mit nicht konstanter Funktion vote
können Sie den Transaktions-Hash nur sofort zurückerhalten, da die Transaktion möglicherweise nie abgebaut wird. Oder es könnte mehrere Blöcke dauern, wie durch „Warten auf zu minende Transaktion ...“ angezeigt. Empfohlene Überprüfung: Was ist der Unterschied zwischen einer Transaktion und einem Anruf?
Ereignisse werden benötigt, um den "Rückgabewert" von zu erhalten vote
.
Beispiel zum Hinzufügen und Auslösen eines event
:
contract answer{
// ...
event VoteEvent(string ID, bool returnValue);
function vote(string ID, uint qNum, uint ans) returns (bool) {
// ...
VoteEvent(ID, true);
return true;
}
}
Siehe Vertragsereignisse für die verschiedenen Möglichkeiten, Ereignisdaten mit web3.js zu überwachen und abzurufen.
vote
vielleicht return false
, zum Beispiel wenn Sie bereits abgestimmt haben, könnte der Rückgabewert hilfreich sein, damit andere Verträge Dinge wie tun können if (!someContract.vote("ak", 7, 2)) {...}
. Rückgabewerte können von anderen Verträgen verwendet werden, aber web3.js kann nur Ereignisse verwenden. Wenn dies immer der Fall ist return true
, kann der boolesche Wert wahrscheinlich entfernt und das Ereignis zu etwas wie vereinfacht werden UserVoted(string ID)
.
Ahmed Achtar
require
mit der vom Operator negierten Bedingung!
anstelle von verwendenthrow
.