solidity投票合约在bcos上的部署及解析(一)

http://wiki.jikexueyuan.com/project/solidity-zh/solidity-example.html
投票合约的代码来自solidity官方文档,我将对这个合约进行简单分析

/// @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),简单的找出一个数组中的最大值,即计算出胜出提案。

你可能感兴趣的:(BCOS学习)