Hi,
I have been testing a contract using the Solidity Browser, but when I deploy the same contract on my private node, it doesn't seem to work the same as in the Solidity Browser. I have tried manually compiling the code of the contract and it didn't make any difference.
Here is the contract:
pragma solidity ^0.4.2;
contract Mortal {
address owner;
event Killed(address indexed from);
function Mortal() {
owner = msg.sender;
}
function kill() {
if (msg.sender == owner) {
Killed(owner);
suicide(owner);
}
}
}
contract Voting is Mortal {
struct Voter {
address voterAddress;
uint hasRightToVote;
uint voted;
address delegate;
}
struct Slide {
uint number;
uint voteCount;
uint score;
uint avgScore;
}
address public chairperson;
mapping(address => Voter) public voters;
mapping(uint => Slide) public slides;
uint public totalSlides;
uint public totalVotes;
uint public totalVoters;
event GivenRightToVote(address indexed chairperson, address indexed voter);
event hasVoted(address indexed voter, uint indexed slideNumber, uint indexed slideScore);
event hasDelegated(address indexed voter, address indexed delegate);
event VoterAlreadyExists(address indexed voter);
event VoterCreated(address indexed voter);
event VoterNotExists(address indexed voter);
event SenderNotChairperson(address indexed sender);
event callInitVoter(address indexed voter, address indexed sender);
event invalidVoter(address indexed voter);
event callGiveRightToVote(address indexed voterAddr);
event initSlideVote(address indexed voterAddr, uint indexed slide);
event VoterNoRightToVote(address indexed voter);
function Voting(uint numberSlides) {
uint i;
for (i = 0; i < numberSlides; i++) {
slides[i] = Slide(i, 0, 0, 0);
}
chairperson = msg.sender;
initVoter(msg.sender);
voters[msg.sender].hasRightToVote = 1;
totalSlides = numberSlides;
totalVoters = 1;
}
function getSlide(uint slideNumber) returns (uint number, uint score, uint voteCount) {
score = slides[slideNumber].score;
voteCount = slides[slideNumber].voteCount;
number = slides[slideNumber].number;
return(number, score, voteCount);
}
function getSlideVoteCount(uint slideNumber) returns (uint voteCount) {
voteCount = slides[slideNumber].voteCount;
return voteCount;
}
function initVoter(address voterAddr) {
callInitVoter(voterAddr, msg.sender);
if(voterAddr == address(0)) {
invalidVoter(voterAddr);
}
if(msg.sender == chairperson) {
if(voters[voterAddr].voterAddress == voterAddr) {
VoterAlreadyExists(voterAddr);
} else {
VoterNotExists(voterAddr);
voters[voterAddr] = Voter(voterAddr, 0, 0, address(0));
totalVoters += 1;
}
VoterCreated(voterAddr);
} else {
SenderNotChairperson(msg.sender);
}
}
event unauthorizedCallerGiveRightToVote(address indexed voter);
function giveRightToVote(address voterAddr) {
callGiveRightToVote(voterAddr);
if(msg.sender == chairperson) {
if(voters[voterAddr].voterAddress == 0x0000000000000000000000000000000000000000) {
VoterNotExists(voterAddr);
initVoter(voterAddr);
} else {
VoterAlreadyExists(voterAddr);
}
voters[voterAddr].hasRightToVote = 1;
GivenRightToVote(chairperson, voterAddr);
} else {
unauthorizedCallerGiveRightToVote(voterAddr);
}
}
event callVote(address indexed voter, uint indexed slide, uint256 indexed score);
event VoterNotAllowedToVote(address indexed voter);
event VoterAllowedToVote(address indexed voter);
event ChairpersonNotAllowedToVote(address indexed voter);
event VoterExists(address indexed voter);
function vote(uint slide, uint256 score) {
Voter voter;
callVote(msg.sender, slide, score);
if(msg.sender == chairperson) {
ChairpersonNotAllowedToVote(msg.sender);
} else {
if(msg.sender == address(0)) {
VoterNotExists(msg.sender);
} else {
voter = voters[msg.sender];
if(voter.hasRightToVote != 1) {
VoterNoRightToVote(msg.sender);
}
if(voter.hasRightToVote == 1) {
VoterExists(msg.sender);
VoterAllowedToVote(msg.sender);
voter.voted += 1;
totalVotes ++;
slides[slide].voteCount += 1;
slides[slide].score += score;
hasVoted(msg.sender, slide, score);
}
}
}
}
function vote2(uint slide, uint score) {
Voter voter;
callVote(msg.sender, slide, score);
voter = voters[msg.sender];
if(voter.voterAddress != address(0)) {
VoterExists(msg.sender);
if(msg.sender != chairperson) {
if(voter.hasRightToVote == 1) {
VoterAllowedToVote(msg.sender);
voter.voted ++;
totalVotes ++;
slides[slide].voteCount ++;
slides[slide].score += score;
hasVoted(msg.sender, slide, score);
} else {
VoterNoRightToVote(msg.sender);
}
} else {
ChairpersonNotAllowedToVote(msg.sender);
}
} else {
VoterNotExists(msg.sender);
}
}
function vote3(uint slide, uint score) {
Voter voter = voters[msg.sender];
callVote(msg.sender, slide, score);
VoterExists(msg.sender);
VoterAllowedToVote(msg.sender);
voter.voted += 1;
totalVotes += 1;
slides[slide].voteCount += 1;
slides[slide].score += score;
hasVoted(msg.sender, slide, score);
}
function winningSlide() constant returns (uint winningSlide) {
uint winningScore = 0;
for (uint p = 0; p < totalSlides; p++) {
if (slides[p].score > winningScore) {
winningScore = slides[p].score;
winningSlide = p;
}
}
return(winningSlide);
}
// Calls winningProposal() function to get the index
// of the winner contained in the proposals array and then
// returns the name of the winner
function winnerCount() constant returns (uint voteCount) {
uint winnerSlide;
winnerSlide = winningSlide();
voteCount = slides[winnerSlide].voteCount;
return(voteCount);
}
function winnerScore() constant returns (uint score) {
uint winnerSlide = winningSlide();
score = slides[winnerSlide].score;
return(score);
}
// Delegate vote to address _to_
function delegate(address to) {
Voter sender = voters[msg.sender];
if (sender.voted != 0) throw;
while (voters[to].delegate != address(0) &&
voters[to].delegate != msg.sender)
to = voters[to].delegate;
if (to == msg.sender)
throw;
for (uint i = 0; i < totalSlides; i++) sender.voted += 1;
sender.delegate = to;
Voter delegate = voters[to];
hasDelegated(msg.sender, to);
}
}
The biggest issue has been with the vote functions (vote, vote2 and vote3). I started with vote and couldn't get it to work, so I ended up creating a simpler version of it, which is vote3. Whenever I execute it against my private node, it doesn't send any event. I can see the transaction being mined, but I get no Event despite having defined a listener for all the events. I can see Events from other functions, such as initVoter, but I can't get the vote, vote2 or vote3 functions to work.
In my mind, vote3 should trigger the event the callVote event, but it doesn't seem to.
If I run the
> voting.initVoter(eth.accounts[1], {from: eth.accounts[0]});
, I get the following events:
> callInitVoter:{"sender":"0xdf5642b3889f4a90a2d9e0c8475e30337cb8ba4f","voter":"0xbc006b353770becc7fdecfd11eff9633a3ea651f"}
VoterNotExists: {"voter":"0xbc006b353770becc7fdecfd11eff9633a3ea651f"}
VoterCreated: {"voter":"0xbc006b353770becc7fdecfd11eff9633a3ea651f"}
If I run
> voting.giveRightToVote(eth.accounts[1], {from: eth.accounts[0]});
, I get the following events:
> callGiveRightToVote: {"voterAddr":"0xbc006b353770becc7fdecfd11eff9633a3ea651f"}
VoterAlreadyExists: {"voter":"0xbc006b353770becc7fdecfd11eff9633a3ea651f"}
GivenRightToVote: {"chairperson":"0xdf5642b3889f4a90a2d9e0c8475e30337cb8ba4f","voter":"0xbc006b353770becc7fdecfd11eff9633a3ea651f"}
but if I run
> voting.vote3(1, 123, {from: eth.accounts[0]});
, I get nothing, no events whatsoever.
If I check some of the variables being updated by the functions, they are not being updated.
The reason for so many events is that I have been using them to troubleshoot the code.
In the Solidity Browser, though, it shows all the Events being triggered and the variables as being updated.
I am pretty new at this and i have no idea what is happening here.
My private node is runnning geth version 1.5.3-unstable, but I have also tried it on a separate node running geth version 1.4.8-stable and i had the same issue.
The Solidity version is 0.4.4+commit.4633f3de.Linux.g++ .
As an aside, I have also ran the contract through Mist and it works perfectly fine. All the events are being triggered and the variables updated.
I am at a total loss.
Thanks a lot in advance for the help,
Bertrand.
Comments