汪晓明对区块链、以太坊的思考

记录创业、生活的所思所感,探讨去中心化思想,推动区块链的发展。

我推出了《VIP区块链技术开发视频》限时9.6折(2/06之前3795元,以后每周一涨价200元,直到恢复原价3950元),欢迎订购!

区块链技术(七):以太坊投票智能合约案例

这个例子相对复杂一些,用到了以太坊编程语言Solidity的很多特性。例子实现了一个投票智能合约。电子投票系统的一个主要问题是如何分配合理的权限给正确的人,并且要防止篡改。这个例子不能解决所有问题,但是实现了如何去委托投票,整个投票计数过程是自动且完全透明的。

功能上首先要为投票设立一个简称创建一个合约,发起者作为主席来给每一个独立的地址分配权限。每一个参与者可以自己投票或者委托给信任的人。程序最后会返回得票数最多的那个提议。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// 一个有委托功能的投票系统
contract Ballot {

  // 定义一个复杂类型,后面作为变量来使用,
  // 代表一个投票人。
  struct Voter {
    unit weight; // weight在代表投票过程中会累积
    bool voted; // 如果值为true,代表这个投票人已经投过票
    address delegate; // 投票人地址
    unit vote; // 当前投票的索引
  }

  // 代表一份提议的数据结构 
  struct Posposal {
    bytes32 name; // 提议的名称
    unit voteCount; // 提议接受的投票数
  }

  // 定义投票发起人
  address public chairperson;

  // 这个状态变量存储了所有潜在投票人
  mapping(address => Voter) public voters;

  // 定义动态数组存储所以提议
  Posposal[] public proposals;

  // 传入提议名称来定义一个投票对象
  function Ballot(bytes32[] proposalNames){
    chairperson = msg.sender;
    voters[chairperson].weight = 1;

    // 把传入的提议名称创建一个提议,并加入到前面定义的提议数组
    for(unit i = 0; i < proposalNames.length; i++){
      // 创建一个临时提议对象,加入提议数组
      proposals.push(Proposal({
        name: proposalNames[i],
        voteCount: 0;
      }));
    }
  }

  // 给投票人分配投票权限,这个操作只有发起人(主席)才可以
  function giveRightToVote(address: voter){
    if(msg.sender != chairperson || voter.voted) {
      throw;
    }
    voters.weight = 1;
  }

  // 委托投票给另外一个投票人
  function delegate(address to){
    // 找出委托发起人,如果已经投票,终止程序
    Voter sender = voters[msg.sender];
    if(sender.voted)
      throw;

    while(voters[to].delegate != address[0] && 
          voters[to].delegate != msg.sender){
      to = voters[to].delegate;
    }

    // 发起人、委托人不能是同一个,否则终止程序
    if(to == msg.sender){
      throw;
    }

    // 标识发起人已经投过票
    sender.voted = true;
    sender.delegate = to;
    Voter delegate = voters[0];
    if (delegate.voted) {
      // 投票成功,投票总数加上相应的weight
      proposals[delegate.vote].voteCount += sender.weight;
    }
    else {
      // 如果还没投票,发起人weight赋值给委托人
      delegate += sender.weight;
    }
  }

  // 投票给某个提议
  function vote(unit proposal) {
    Voter sender = voters[msg.sender];
    if (sender.voted) 
      throw;
    sender.voted = true;
    sender.voter = proposal;

    proposals[proposal].voteCount += sender.weight;
  }

  // 找出投票数最多的提议
  function winningProposal() constant returns (winningProposal)
  {
    unit winningVoteCount = 0;
    for (unit p = 0; p < voteCount; p++) {
      if (proposals[p].voteCount > winningVoteCount){
        winningVoteCount = proposals[p].voteCount;
        winningProposal = p;
      }
    }
  }
  
}

以上就是完整的投票智能合约,对新人有点复杂,需要花点时间学习,后面我们通过更多例子加深对代码的理解。