在以太坊Dapp终极教程——如何构建一个完整的全栈去中心化应用(一)中,我们已经完成了一切所需的设置;在以太坊Dapp终极教程——如何构建一个完整的全栈去中心化应用(二)中,让我们通过列出将在选举中运行的候选人来继续构建智能合约并完成客户端程序。下面我们来完成投票部分,现在让我们添加在选举中投票的能力。
让我们定义一个选民voters
映射到智能合约,以跟踪在选举中投票的账户,如下所示:
contract Election {
// ...
// Store accounts that have voted
mapping(address => bool) public voters;
// ...
}
现在让我们添加一个投票vote
函数:
contract Election {
// ...
// Store accounts that have voted
mapping(address => bool) public voters;
// ...
function vote (uint _candidateId) public {
// require that they haven't voted before
require(!voters[msg.sender]);
// require a valid candidate
require(_candidateId > 0 && _candidateId <= candidatesCount);
// record that voter has voted
voters[msg.sender] = true;
// update candidate vote Count
candidates[_candidateId].voteCount ++;
}
}
此函数的核心功能是通过从候选candidates
映射中读取候选结构并使用递增运算符(++)将voteCount
增加1来增加候选者的投票计数。让我们看看它做的其他一些事情:
- 1.它接受一个论点。这是一个带有候选者id的无符号整数。
- 2.它是公开可见的,因为我们想要一个外部帐户来调用它。
- 它添加了投票给我们刚刚创建的选民映射的帐户。这将使我们能够跟踪选民在选举中投票的情况。我们使用Solidity提供的全局变量
msg.sender
访问调用此函数的帐户。
- 它实现了require语句,如果不满足条件,它将停止执行。首先要求选民之前没有投票。我们通过从映射中读取带有
msg.sender
的帐户地址来完成此操作。如果它在那里,该帐户已经投票。接下来,它要求候选ID有效。候选id必须大于零且小于或等于总候选计数。
现在,你的完整合约代码应如下所示:
pragma solidity ^0.4.2;
contract Election {
// Model a Candidate
struct Candidate {
uint id;
string name;
uint voteCount;
}
// Store accounts that have voted
mapping(address => bool) public voters;
// Read/write candidates
mapping(uint => Candidate) public candidates;
// Store Candidates Count
uint public candidatesCount;
function Election () public {
addCandidate("Candidate 1");
addCandidate("Candidate 2");
}
function addCandidate (string _name) private {
candidatesCount ++;
candidates[candidatesCount] = Candidate(candidatesCount, _name, 0);
}
function vote (uint _candidateId) public {
// require that they haven't voted before
require(!voters[msg.sender]);
// require a valid candidate
require(_candidateId > 0 && _candidateId <= candidatesCount);
// record that voter has voted
voters[msg.sender] = true;
// update candidate vote Count
candidates[_candidateId].voteCount ++;
}
}
测试投票功能
现在让我们为election.js
测试文件添加一个测试:
it("allows a voter to cast a vote", function() {
return Election.deployed().then(function(instance) {
electionInstance = instance;
candidateId = 1;
return electionInstance.vote(candidateId, { from: accounts[0] });
}).then(function(receipt) {
return electionInstance.voters(accounts[0]);
}).then(function(voted) {
assert(voted, "the voter was marked as voted");