以太坊智能合约投票示例Java模拟实现
2018-01-05 20:08
441 查看
使用java语言模拟实现以太坊智能合约执行过程
投票合约实现类:contract.BallotContract.javapackage contract; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Created by haibiao on 2018/1/5. */ public class BallotContract { private static final String TAG = "BallotContract"; /**身份审核(赋予投票权)截止时间*/ public static final long VERIFY_DEADLINE = 1515168000000L;//2018/01/06 00:00:00.000 /**投票(委托)截止时间*/ public static final long VOTE_DEADLINE = VERIFY_DEADLINE + (1000 * 60 * 2);//身份审核结束后的2分钟内为投票时间 /**合约单实例*/ private static BallotContract INSTANCE; /**合约创建者(投票主持人)地址*/ private final String mChairAddress; /**投票者状态保存*/ private final Map<String,Voter> mVoterMap = new HashMap<>(); /**提案列表*/ private final Proposal[] mProposals; /**投票结果,得票数最多的提案索引*/ private int[] mVoteResult; /**每次调用合约都会包含的上下文*/ private Ctx ctx; /** * 创建合约,只会执行一次 * @param ctx 调用时的上下文 * @param names 提案名称数组 */ public static void create(Ctx ctx,String[] names){ if(INSTANCE == null){ INSTANCE = new BallotContract(ctx,names); } } /** * 获取合约实例 * @param ctx 调用时的上下文 * @return 投票合约实例 */ public static BallotContract getDefault(Ctx ctx){ INSTANCE.ctx = ctx; return INSTANCE; } /** * 投票合约构造函数,初始化一些变量 * @param ctx 上下文 * @param names 提案名称数组 */ private BallotContract(Ctx ctx, String[] names) { mChairAddress = ctx.msg.sender; Voter chair = new Voter(); chair.weight = 1; mVoterMap.put(mChairAddress,chair); mProposals = new Proposal[names.length]; for(int i = 0 ; i < mProposals.length ; i++){ mProposals[i] = new Proposal(); mProposals[i].name = names[i]; } } /** * 获取投票结果,只有当投票阶段结束且调用了一次统票方法才会有值 * @return 投票结果 */ public int[] < 4000 span class="hljs-title">getVoteResult(){ return mVoteResult; } /** * 赋予投票权,只能主持人调用 * @param address 赋予的目标地址 * @return 赋予投票权结果 */ public boolean giveVoteRight(String address){ if(System.currentTimeMillis() > VERIFY_DEADLINE){ log("giveVoteRight time already over"); return false; } if(!mChairAddress.equals(ctx.msg.sender)){ log("giveVoteRight only the chairman can call"); return false; } Voter voter = mVoterMap.get(address); if(voter == null){ voter = new Voter(); voter.weight = 1; mVoterMap.put(address,voter); log("giveVoteRight success , address = " + address); return true; }else{ log("giveVoteRight failed , yet give,address = "+address); } return false; } /** * 委托操作,将投票权委托给他人 * @param to 受托人地址 * @return 委托结果 */ public boolean delegate(final String to){ final long curr = System.currentTimeMillis(); if(curr <= VERIFY_DEADLINE){ log("delegate failed,The delegate hasn't begun"); return false; } if(curr > VOTE_DEADLINE){ log("delegate failed,delegate already over "); return false; } final String sender = ctx.msg.sender; Voter fromVoter = mVoterMap.get(sender); if(fromVoter == null //没有投票权 || fromVoter.weight <= 0 //没有投票权 || sender.equals(to) //委托给自己 ){ log("delegate failed"); return false; } String toTemp = to; Voter toVoter = null; while (true){ toVoter = mVoterMap.get(toTemp); if(toVoter == null//受托人没有投票权 || toVoter.weight <= 0 //受托人没有投票权 ){ return false; } if(toVoter.delegate == null){ toVoter.weight += fromVoter.weight; fromVoter.weight = 0; fromVoter.delegate = toTemp; return true; }else{ toTemp = toVoter.delegate; } } } /** * 执行投票 * @param index 提案的索引 * @return 投票结果 */ public boolean vote(int index){ final long curr = System.currentTimeMillis(); if(curr <= VERIFY_DEADLINE){ log("vote failed,The delegate hasn't begun"); return false; } if(curr > VOTE_DEADLINE){ log("vote failed,vote already over"); return false; } if(index < 0 || index >= mProposals.length){ log("proposal index error , index = "+index); return false; } final String sender = ctx.msg.sender; Voter voter = mVoterMap.get(sender); if(voter == null //没有投票权 || voter.weight <= 0 //没有投票权 ){ log("vote failed"); return false; } final Proposal proposal = mProposals[index]; proposal.voteCount += voter.weight; voter.weight = 0; voter.proposalIndex = index; return true; } /** * 统计票数,任何人都可以随时调用,当投票阶段结束后,调用此方法会将会保存最终的投票结果 * @return 当前统票结果 */ public int[] statisticsVote(){ if(System.currentTimeMillis() <= VERIFY_DEADLINE){ log("The statistics vote hasn't begun"); return new int[0]; } final List<Integer> result = new ArrayList<>(1); int maxCount = -1; for(int i = 0 ; i < mProposals.length ; i++){ int count = mProposals[i].voteCount; if(count > maxCount){ maxCount = count; result.clear(); result.add(i); }else if(count == maxCount){ result.add(i); } } int[] arr = new int[result.size()]; for(int i = 0 ; i < arr.length ; i++){ arr[i] = result.get(i); } if(System.currentTimeMillis() > VOTE_DEADLINE){ //投票阶段已结束,保存统票结果 mVoteResult = arr; } log("statistics vote result = "+ Arrays.toString(arr)); return arr; } private static void log(String msg){ System.out.println(String.format("[%s]%s",TAG,msg)); } /** * 投票者数据结构 */ private static class Voter{ int weight;//票数 String delegate;//受托者 int proposalIndex;//提案索引号 } /** * 提案数据结构 */ private static class Proposal{ String name;//提案名称 int voteCount;//提案所得票数 } }
合约调用类:contract.Main.java
package contract; /** * Created by haibiao on 2018/1/5. */ public class Main { public static void main(String[] args){ BallotContract.create(getCtx("sender"),new String[]{"提案1","提案2","提案3","提案4"}); String address001 = "voter_0x001"; boolean result = BallotContract.getDefault(getCtx(address001)).giveVoteRight(address001); log("giveVoteRight result = "+result); } private static Ctx getCtx(String sender){ return new Ctx(new Ctx.Msg(sender)); } private static void log(String msg){ System.out.println(msg); } }
相关文章推荐
- 以太坊智能合约投票示例Java模拟实现
- 智能合约开发——以太坊 DApp 实现 购买通证token
- Java枚举(用Java普通类模拟枚举的实现原理及JDK枚举API使用示例)
- 以太坊数据编码实现;智能合约
- 以太坊智能合约实现代币空投
- web3j开发java或android以太坊智能合约快速入门
- Java枚举(用Java普通类模拟枚举的实现原理及JDK枚举API使用示例)
- 以太坊智能合约开发DApp应用示例
- Java枚举(用Java普通类模拟枚举的实现原理及JDK枚举API使用示例)
- 以太坊智能合约Hello World示例程序
- Java模拟扑克牌洗牌实现生成52张扑克的方法示例
- 了解以太坊区块链智能合约开发从零构建和部署去中心化投票
- 以太坊智能合约虚拟机(EVM)原理与实现
- Java编程实现的模拟行星运动示例
- 以太坊智能合约Hello World示例程序
- AjaxPro.NET实现TextBox智能获取服务端数据功能(Asp.net 2.0)(示例代码下载)
- 用C++和JAVA实现进程调度模拟
- 使用java简单模拟ping和telnet的实现
- 使用JAVA实现签名验证示例程序