solidity投票合約在bcos上的部署及解析(一)
/// @title Voting with delegation.
/// @title 授權投票
contract Ballot
{
// 這裡聲明瞭複雜型別
// 將會在被後面的引數使用
// 代表一個獨立的投票人。
struct Voter
{
uint weight; // 累積的權重。
bool voted; // 如果為真,則表示該投票人已經投票。
address delegate; // 委託的投票代表
uint vote; // 投票選擇的提案索引號
}
// 這是一個獨立提案的型別
struct Proposal
{
bytes32 name; // 短名稱(32位元組)
uint voteCount; // 累計獲得的票數
}
address public chairperson;
//這裡宣告一個狀態變數,儲存每個獨立地址的`Voter` 結構
mapping(address => Voter) public voters;
//一個儲存`Proposal`結構的動態陣列
Proposal[] public proposals;
// 建立一個新的投票用於選出一個提案名`proposalNames`.
function Ballot(bytes32[] proposalNames)
{
chairperson = msg.sender;
voters[chairperson].weight = 1;
//對提供的每一個提案名稱,建立一個新的提案
//物件新增到陣列末尾
for (uint i = 0; i < proposalNames.length; i++)
//`Proposal({...})` 建立了一個臨時的提案物件,
//`proposal.push(...)`新增到了提案陣列`proposals`末尾。
proposals.push(Proposal({name: proposalNames[i],
voteCount: 0
}));
}
//給投票人`voter`參加投票的投票權,
//只能由投票主持人`chairperson`呼叫。
function giveRightToVote(address voter)
{
if (msg.sender != chairperson || voters[voter].voted)
//`throw`會終止和撤銷所有的狀態和以太改變。
//如果函式呼叫無效,這通常是一個好的選擇。
//但是需要注意,這會消耗提供的所有gas。
throw;
voters[voter].weight = 1;
}
// 委託你的投票權到一個投票代表 `to`。
function delegate(address to)
{
// 指定引用
Voter sender = voters[msg.sender];
if (sender.voted)
throw;
//當投票代表`to`也委託給別人時,尋找到最終的投票代表
while (voters[to].delegate != address(0) &&
voters[to].delegate != msg.sender)
to = voters[to].delegate;
// 當最終投票代表等於呼叫者,是不被允許的。
if (to == msg.sender)
throw;
//因為`sender`是一個引用,
//這裡實際修改了`voters[msg.sender].voted`
sender.voted = true;
sender.delegate = to;
Voter delegate = voters[to];
if (delegate.voted)
//如果委託的投票代表已經投票了,直接修改票數
proposals[delegate.vote].voteCount += sender.weight;
else
//如果投票代表還沒有投票,則修改其投票權重。
delegate.weight += sender.weight;
}
///投出你的選票(包括委託給你的選票)
///給 `proposals[proposal].name`。
function vote(uint proposal)
{
Voter sender = voters[msg.sender];
if (sender.voted) throw;
sender.voted = true;
sender.vote = proposal;
//如果`proposal`索引超出了給定的提案陣列範圍
//將會自動丟擲異常,並撤銷所有的改變。
proposals[proposal].voteCount += sender.weight;
}
///@dev 根據當前所有的投票計算出當前的勝出提案
function winningProposal() constant
returns (uint winningProposal)
{
uint winningVoteCount = 0;
for (uint p = 0; p < proposals.length; p++)
{
if (proposals[p].voteCount > winningVoteCount)
{
winningVoteCount = proposals[p].voteCount;
winningProposal = p;
}
}
}
}
1.合約定義了倆個結構體,代表投票人的Voter和代表提案的Proposal;與這倆個結構體對應的voters(對映,我的理解是相當於對Voter的一個索引)和proposals(可變陣列)分別用於儲存投票人結構體和提案結構體。在這裡,要找到投票人,需要一個投票人地址(address);而要找到提案,需要一個訪問可變陣列的索引。
2.address public chairperson指的是建立投票的那個投票人
3.function Ballot(bytes32[] proposalNames)函式用於建立一個新投票,建立人是當前合約的呼叫者,具體邏輯如下:
a:得到呼叫者的地址
b:在投票人對映(voters)中找到這個地址,將它的其權重設為1;(這個權重僅代表本次投票)
c:將該地址提供的所有提案(函式的輸入引數proposalNames)儲存到全域性的天陣列中
4:function giveRightToVote(address voter)該函式用於給需要投票的人投票權,只是簡單的將需要投票的投票人地址的權重置為1(多人投票時,該函式需呼叫多次)
**5**function delegate(address to)委託投票權給一個投票人(某幾個投票人不想投票,選擇將自己的權重轉讓給一個信的過的人(代表)),通過傳入的投票人地址找到這個人,分以下情況:
a:該地址已將投票權轉讓,通過投票人結構體的delegate地址找到最終可以投票的人。
b:未轉讓但已投票,通過投票人結構體的vote索引找到已投票的提案直接將票投給該提案。
c:未轉讓未投票,將自己權重加到代表的權重上。(在這之前已經將投票標誌(voted)置為true表示自己已投票,喪失投票權)
**6**function vote(uint proposal),投出選票將相應的提案找出,並在得票額上加上投票人的權重。
**7**function winningProposal() constant returns (uint winningProposal),簡單的找出一個數組中的最大值,即計算出勝出提案。