Solidity by Example详解 - Voting
Example地址:https://solidity.readthedocs.io/en/develop/solidity-by-example.html#voting
Voting程序的功能:
这个智能合约实现了一种在区块链上公开投票的功能。
部署该智能合约的人称为chairperson(主席),主席的作用为:
1. 在合约部署时,创建一系列proposals(提案),供大家投票
2. 在合约部署后,主席有权邀请人来投票,对应于代码中的giveRightToVote(address)方法
投票者(包括主席和其他参与投票的人)的投票权重均为1,他们可以:
1. 给一个提案投票(每人只有一票,只能投一个提案)
2. 也可以将自己的投票权委托给另一个投票者,则被委托人的投票权重变为2(票数还是1,只能投一个提案),如果被委托人还没投票,则当他投票时,一票抵两票;如果被委托人已经投票,则给他所投的提案再加一票。
在区块链上实现这个功能的好处为:投票过程公开透明,不可篡改
程序分析:
pragma solidity ^0.4.; /// 委托投票
contract Ballot {
// 投票人结构体
struct Voter {
uint weight; // 投票权重(可通过委托增加)
bool voted; // 是否已投票标识 ture-已投,false-未投
address delegate; // 委托人(可以委托另一人带自己投票)
uint vote; // 所投的提案(提案数组的下标)
} // 提案结构体
struct Proposal {
bytes32 name; // 提案名(最长32byte)
uint voteCount; // 累计票数
} address public chairperson; //主席(合约创建人地址) //声明一个投票人字典,类似python中的字典数据结构 voters = {addr1: voter1, addr2: voter2, addr3: voter3}
mapping(address => Voter) public voters; // 用于储存Proposal结构体的可变长数组
Proposal[] public proposals; /// 构造函数,只执行一次,传入提案数组
function Ballot(bytes32[] proposalNames) public {
chairperson = msg.sender; // 主席被初始化为delopy合约的人
voters[chairperson].weight = ; // 主席的权重为1 // 初始化提案数组为:名称 + 初始票数(0)
for (uint i = ; i < proposalNames.length; i++) {
// `Proposal({...})` 创建一个临时的Proposal对象
// `proposals.push(...)` 将其push进proposals数组中
proposals.push(Proposal({
name: proposalNames[i],
voteCount:
}));
}
} // 给予投票人投票的权利
function giveRightToVote(address voter) public {
// 通过require来做输入检查,如require中的运算结果为false,则合约终止运行,且不改变状态变量的值,退回gas消耗(旧版本可能没实现,新版本将实现)
require(
(msg.sender == chairperson) && //主席才能执行该方法
!voters[voter].voted && // 投票人没投过票
(voters[voter].weight == ) // 投票人权重为0
);
voters[voter].weight = ; //给投票人赋权重为1
} /// 将自己投票权给另一人 `to`.
function delegate(address to) public {
// 声明Voter sender为引用类型变量,意味着在delegate()方法内对sender做的改变将会传递到方法外
Voter storage sender = voters[msg.sender];
require(!sender.voted); //要求sender在转让投票权前,自己未投票 // 不能将投票权转移给自己
require(to != msg.sender); // 当投票代表`to`也委托给别人时,寻找到最终的投票代表,将投票权转让
// 通常来说,这样的循环结构有点危险,如果执行时间长,可能会将gas消耗殆尽,gas消耗完时合约可能不执行或被卡住.
while (voters[to].delegate != address()) {
to = voters[to].delegate; // 有可能死循环,加以下检查.
require(to != msg.sender);
} // 通过引用传递修改voters[msg.sender]的属性,投票权被转让后标记为已投票
sender.voted = true;
sender.delegate = to; Voter storage delegate_ = voters[to];
if (delegate_.voted) {
//如果委托的投票代表已经投票了,直接修改票数
proposals[delegate_.vote].voteCount += sender.weight;
} else {
//如果投票代表还没有投票,则修改其投票权重。
delegate_.weight += sender.weight;
}
} /// 投出你的选票(包括委托给你的选票)
function vote(uint proposal) public {
Voter storage sender = voters[msg.sender];
require(!sender.voted);
sender.voted = true;
sender.vote = proposal; // If `proposal` is out of the range of the array,
// this will throw automatically and revert all
// changes.
//数组下标越界自动报错
proposals[proposal].voteCount += sender.weight;
} /// 根据当前所有的投票计算出当前的胜出提案.
// view关键字代表不对状态变量进行更新操作(但可以查看),会减少gas消耗
function winningProposal() public view
returns (uint winningProposal_)
{
uint winningVoteCount = ;
for (uint p = ; p < proposals.length; p++) {
if (proposals[p].voteCount > winningVoteCount) {
winningVoteCount = proposals[p].voteCount;
winningProposal_ = p;
}
}
} //获得胜出提案的名称
function winnerName() public view
returns (bytes32 winnerName_)
{
winnerName_ = proposals[winningProposal()].name;
}
}
Solidity by Example详解 - Voting的更多相关文章
- 详解 Solidity 事件Event - 完全搞懂事件的使用
很多同学对Solidity 中的Event有疑问,这篇文章就来详细的看看Solidity 中Event到底有什么用? 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊. ...
- truffle使用详解
truffle使用详解 truffle是什么 Truffle测试环境 安装truffle truffle项目结构解析 文件编译 truffle的配置文件 移植 与合约进行交互 1.truffle是什么 ...
- django用户投票系统详解
投票系统之详解 1.创建项目(mysite)与应用(polls) django-admin.py startproject mysite python manage.py startapp polls ...
- Linq之旅:Linq入门详解(Linq to Objects)
示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...
- 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)
一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...
- Java 字符串格式化详解
Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...
- Android Notification 详解(一)——基本操作
Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...
- Android Notification 详解——基本操作
Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...
随机推荐
- PS图片去色
快捷键:Ctrl+Shift+U 或者:图像-调整-去色
- 微信小程序初识
http://lib.csdn.net/article/wechat/46742 微信小程序的前途和定位有什么疑惑?点进去 简单先记几个印象名词:流量入口,线下是重点,“即用即走”适合低频工具类产品. ...
- 一个简单的定时表达式(HH:mm:ss)解析
前言 为客户开发了一个日志监控程序,监听各频道是否正常工作.其中有一个功能是这样的,当所有频道正常运行一段时间后,语音提示值班人员系统运行正常.一开始,想法比较简单,设置了一个变量,在线程不断轮询的过 ...
- SpringBoot简单连接数据库以及查询数据
实现大概思路:配置数据库环境-->实体类-->新建**Repostory接口并且继承JpaRepository-->配置URL映射以及请求方式- 首先,在数据库中新建名称为dbgir ...
- iOS原生和H5的相互调用
为什么现在越来越多的APP中开始出现H5页面? 1,H5页面开发效率更高,更改更加方便: 2,适当缩小APP安装包的大小: 3,蹭热点更加方便,比如五一,十一,双十一搞活动: 那么为什么说H5无法取代 ...
- Yii的数组助手类
获取值 用原生PHP从一个对象.数组.或者包含这两者的一个复杂数据结构中获取数据是非常繁琐的. 你首先得使用isset 检查 key 是否存在, 然后如果存在你就获取它,如果不存在, 则提供一个默认返 ...
- Eclipse搭建Maven项目之准备工作
Maven是优秀的Java项目对象模型解决方案,意为知识的积累(意地绪文),Maven可以方便的解决Java项目包依赖问题,通过配置pom.xml引入依赖,并自动引入其他依赖. 操作系统版本:wind ...
- C#中ASCII码学习心得
1.利用调用ASCIIEncoding类来实现各种转换.如简单个ACS码和int转换. ***利用(int)ASCIIEncoding类对象.GetBytes(character)[0]得到整数: p ...
- 吾八哥学Selenium(四):操作下拉框select标签的方法
我们在做web页面自动化测试的时候会经常遇到<select></select>标签的下拉框,那么在Python里如何实现去操作这种控件呢?今天就给大家分享一下这个玩法.为了让大 ...
- Service IP 原理 - 每天5分钟玩转 Docker 容器技术(137)
Service Cluster IP 是一个虚拟 IP,是由 Kubernetes 节点上的 iptables 规则管理的. 可以通过 iptables-save 命令打印出当前节点的 iptable ...