zoukankan      html  css  js  c++  java
  • 投票机制设计

    公链

    说明:转载请说明出处,无端盗用必追责!

    黑名单功能

    使用:

    1. 限制交易,即在gossipswitch提供blacklist,限制某些账户的交易;

    2. 惩罚机制,如果被列入黑名单,不能参与出块;

    设计:

    1. 发起黑名单请求(必须是超级节点,才能发起设置黑名单的请求),附带惩罚原因,或者是公示的标记;

    2. 超级节点对黑名单的提议内容进行审核投票,为了快速达成一致,超过1/3节点投票通过即设置;

    3. 支持黑名单的设置和取消功能,建议投票超过2/3才能取消;

    4. 投票过程分为两种:投赞成票,弃权(不进行投票);

    5. 支持移除黑名单,也采用投票机制;

    6. 一旦对某个黑名单进行投票,则不能取消;

    代码实现:

      1 pragma solidity >=0.4.24 <0.6.0;
      2 
      3 /*
      4 * 安全操作函数
      5 *  SafeMath to avoid data overwrite
      6 */
      7 library SafeMath {
      8     function mul(uint a, uint b) internal pure returns (uint) {
      9         uint c = a * b;
     10         require(a == 0 || c / a == b, "overwrite error");
     11         return c;
     12     }
     13  
     14     function div(uint a, uint b) internal pure returns (uint) {
     15         require(b > 0, "overwrite error");
     16         uint c = a / b;
     17         require(a == b * c + a % b, "overwrite error");
     18         return c;
     19     }
     20  
     21     function sub(uint a, uint b) internal pure returns (uint) {
     22         require(b <= a, "overwrite error");
     23         return a - b;
     24     }
     25  
     26     function add(uint a, uint b) internal pure returns (uint) {
     27         uint c = a + b;
     28         require(c>=a && c>=b, "overwrite error");
     29         return c;
     30     }
     31 }
     32 
     33 contract JustitiaRight {
     34     uint256 public totalSupply;
     35     
     36     function lockCount(address _account, uint _count) public;
     37     function unlockCount(address _account, uint _count) public;
     38     function residePledge(address _owner) public view returns(uint balance);
     39     
     40     function balanceOf(address _owner) public view returns (uint256 balance);
     41     function transfer(address _to, uint256 _value) public returns (bool success);
     42     function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
     43     function approve(address _spender, uint256 _value) public returns (bool success);
     44     function allowance(address _owner, address _spender) public view returns (uint256 remaining);
     45 }
     46 
     47 contract CandidateManage {
     48     
     49     using SafeMath for uint;
     50     uint256 public totalPledge;
     51     uint constant MINIMUM_PLEDGE_TOKEN = 100;
     52   
     53     JustitiaRight public justitia;
     54     
     55     struct Candidate{
     56         address account;
     57         uint pledge;   // total support pledge
     58         string memo;
     59         uint ranking;
     60         bool isValid;
     61     }
     62     address [] public CandidateList;
     63     mapping(address => Candidate) public candidateLookup;
     64     // mapping(support, totalPledge)
     65     mapping(address => uint256) public balanceOfPledge;
     66 
     67     // event define
     68     event ApplyToCandidateEvent(address, bool, string);
     69     
     70     // criterias that be a candidate 
     71     function candidateCriteria(address candidate, uint256 pledge) private view returns(bool){
     72         uint256 balance = justitia.residePledge(candidate);
     73         if(MINIMUM_PLEDGE_TOKEN <= balance && balance >= pledge){
     74             return true;
     75         }
     76         return false;
     77     }
     78     
     79     // role classify
     80     // normal: account with PR, which has right to vote
     81     // participate: normal account which has participate in vote and has peldge currently
     82     // candidate: account pledge PR to be a candidate
     83     function isNormal(address _account) public view returns(bool){
     84         if(!isParticipate(_account) && !isCandidate(_account)){
     85             return true;
     86         }
     87         return false;
     88     }
     89     
     90     function isParticipate(address _account) public view returns(bool){
     91         if (0 != balanceOfPledge[_account]){
     92             return true;
     93         }
     94         return false;
     95     }
     96   
     97     function isCandidate(address account) public view returns(bool){
     98         return candidateLookup[account].isValid;
     99     }
    100     
    101     // get account balance statistic
    102     function balanceStatistic(address _owner) public view returns (uint256 balance, uint256 pledge){
    103         require(address(0) != _owner);
    104         
    105         uint256 total;
    106         uint256 reside;
    107         
    108         total = justitia.balanceOf(_owner);
    109         reside = justitia.residePledge(_owner);
    110         
    111         require(total.sub(reside) == balanceOfPledge[_owner]);
    112         
    113         return (total, balanceOfPledge[_owner]);
    114     }
    115     
    116     // get candidate information
    117     function candidateState(address candidate) public view returns(uint256, uint256, string){
    118         require(isCandidate(candidate));
    119         uint index;
    120         for(index = 0; index < CandidateList.length; index++){
    121             if(CandidateList[index] == candidate){
    122                 break;
    123             }    
    124         }
    125         return (index, candidateLookup[candidate].pledge, candidateLookup[candidate].memo);
    126     }
    127     
    128     // find index to insert the account by specified candidate in CandidateList
    129     function findIndexOfCandidate(uint pledge) private view returns(uint){
    130         uint index;
    131         for(index = 0; index < CandidateList.length; index++){
    132             if(candidateLookup[CandidateList[index]].pledge <= pledge){
    133                 break;
    134             }
    135         }
    136         return index;
    137     }
    138     
    139     // add applicant to candidate list
    140     function addToCandidateListDescending(address applicant, uint pledge) private returns(uint){
    141         uint index;
    142         index = findIndexOfCandidate(pledge);
    143         CandidateList.push(applicant);
    144         for(uint i = CandidateList.length - 1; i > index; i--){
    145             CandidateList[i] = CandidateList[i - 1];
    146             candidateLookup[CandidateList[i]].ranking = i;
    147         }
    148         CandidateList[index] = applicant;
    149         candidateLookup[CandidateList[index]].ranking = index;
    150         return index;
    151     }
    152     
    153     // candidate list adjustment
    154     function adjustCandidateList(address candidate, uint pledge) public returns(uint){
    155         if(!isCandidate(candidate)){
    156             return addToCandidateListDescending(candidate, pledge);
    157         } 
    158         
    159         uint currentIndex;
    160         uint rightIndex;
    161         for(currentIndex = 0; currentIndex < CandidateList.length; currentIndex++){
    162             if(CandidateList[currentIndex] == candidate){
    163                 break;
    164             }
    165             if(candidateLookup[CandidateList[rightIndex]].pledge >= candidateLookup[candidate].pledge){
    166                 rightIndex++;
    167             }
    168             
    169         }
    170         
    171         // adding
    172         if(rightIndex < currentIndex){
    173             for(uint i = currentIndex; i > rightIndex; i--){
    174                 CandidateList[i] = CandidateList[i - 1];
    175                 candidateLookup[CandidateList[i]].ranking = i;
    176             }
    177         } else {
    178             for(uint j = currentIndex; j < rightIndex; j++){
    179                 CandidateList[j] = CandidateList[j + 1];
    180                 candidateLookup[CandidateList[j]].ranking = j;
    181             }
    182         }
    183         
    184         CandidateList[rightIndex] = candidate;
    185         candidateLookup[CandidateList[rightIndex]].ranking = rightIndex;
    186         return rightIndex;
    187     }
    188     
    189     // apply to candidate 
    190     function ApplyToCandidate(uint pledge, string memo) public returns(bool, string){
    191         require(!isCandidate(msg.sender));
    192         
    193         string memory errors;
    194         if(!candidateCriteria(msg.sender, pledge)){
    195             errors = "errors: some criterias not met.";
    196             emit ApplyToCandidateEvent(msg.sender, false, errors);
    197             return (false, errors);
    198         }
    199         
    200         totalPledge = totalPledge.add(pledge);
    201         justitia.lockCount(msg.sender, pledge);
    202         balanceOfPledge[msg.sender] = balanceOfPledge[msg.sender].add(pledge);
    203         adjustCandidateList(msg.sender, pledge);
    204         candidateLookup[msg.sender].memo = memo;
    205         candidateLookup[msg.sender].isValid = true;
    206         candidateLookup[msg.sender].pledge = candidateLookup[msg.sender].pledge.add(pledge);
    207         candidateLookup[msg.sender].account = msg.sender;
    208         emit ApplyToCandidateEvent(msg.sender, true, errors);
    209         return (true, errors);
    210     }
    211     
    212     // get candidates
    213     function Candidates() public view returns(address[]){
    214         return CandidateList;
    215     }
    216 }
    217 
    218 
    219 contract BlackListElection {
    220     using SafeMath for uint;
    221     struct BlackListItem{
    222         string reason;
    223         address []approveAccounts;
    224         address []rejectAccounts;
    225         mapping(address => bool) approveRecords;
    226         mapping(address => bool) rejectRecoeds;
    227         bool isValid;
    228         uint index;
    229     }
    230     mapping(address => BlackListItem) public blackListItemLookup;
    231     address [] public blackListProcessing;
    232     
    233     function isRegiste(address _account) public view returns(bool){
    234         return blackListItemLookup[_account].isValid;
    235     }
    236     
    237     function toBlackList(address _account, string reason) public returns(uint){
    238         if(!isRegiste(_account)){
    239             blackListItemLookup[_account].reason = reason;
    240             blackListItemLookup[_account].approveAccounts.push(_account);
    241             blackListItemLookup[_account].approveRecords[msg.sender] = true;
    242             blackListItemLookup[_account].isValid = true;
    243             blackListItemLookup[_account].index = blackListProcessing.push(_account).sub(1);
    244         } else {
    245             if(!blackListItemLookup[_account].approveRecords[msg.sender]){
    246                 blackListItemLookup[_account].approveAccounts.push(_account);
    247                 blackListItemLookup[_account].approveRecords[msg.sender] = true;
    248             }
    249         }
    250         return blackListItemLookup[_account].approveAccounts.length;
    251     }
    252     
    253     function blackListToProcess() public view returns(address[]){
    254         return blackListProcessing;
    255     }
    256     
    257     function removeBlackList(address _account) public {
    258         require(isRegiste(_account));
    259         delete blackListProcessing[blackListItemLookup[_account].index];
    260         delete blackListItemLookup[_account];
    261     }
    262 }
    263 
    264 
    265 contract BlackListManage is BlackListElection{
    266     
    267     uint public thresHoldToAddBlackList;
    268     uint public thresHoldToRrmoveBlackList;
    269     
    270     struct BlackList {
    271         uint date;
    272         bool isValid;
    273     }
    274     mapping(address => BlackList) public blackListLookup;
    275     address [] public blackList;
    276     
    277     event AddToBlackListEvent(address, string);
    278     
    279     function isInBlackList(address _account) public view returns(bool){
    280         return blackListLookup[_account].isValid;
    281     }
    282     
    283     function voteForBlacklist(address _account, string comment) public {
    284         uint supporters = toBlackList(_account, comment);
    285         if (supporters >=  thresHoldToAddBlackList){
    286             blackListLookup[_account].date = now;
    287             blackListLookup[_account].isValid = true;
    288             blackList.push(_account);
    289             removeBlackList(_account);
    290             emit AddToBlackListEvent(_account, blackListItemLookup[_account].reason);
    291         }
    292     }
    293     
    294     function getBlackList() public view returns(address[]){
    295         return blackList;
    296     }
    297     
    298 }
    299 
    300 /* 
    301 *  系统合约调用
    302 *  管理选举情况,包括:选举,取消选举,选举情况统计等
    303 */
    304 contract ElectionManage is CandidateManage, BlackListManage {
    305     
    306     using SafeMath for uint;
    307     uint public totalNodes;
    308     uint constant ENTRY_HRESHOLD = 100;
    309     bool private mainNetSwitch;
    310     uint constant MAINNET_ONLINE_THRESHOLD = 1000;
    311     
    312     event MainNetOnlineEvent(uint, uint);
    313     event IssueVoteEvent(address, address, uint);
    314     event AdjustmentVoteEvent(address, address, uint);
    315     
    316     struct Election{
    317         bool isValid;
    318         address[] participates;
    319         mapping(address => uint) election; 
    320     }
    321     // record candidate election
    322     mapping(address => Election) private candidateElection;
    323     
    324     // constructor
    325     constructor (address token, uint nodeNum) public {
    326         justitia = JustitiaRight(token);
    327         totalNodes = nodeNum;
    328         thresHoldToAddBlackList = nodeNum.div(3);
    329         thresHoldToRrmoveBlackList = thresHoldToAddBlackList.mul(2) + 1;
    330     }
    331     
    332     // try to online main network
    333     // we assume that once mainnet onlie, it will onlie forever 
    334     function tryToOnlineMainNet() private {
    335         // only state changed, emit event
    336         if(!mainNetSwitch){
    337             if(totalPledge >= MAINNET_ONLINE_THRESHOLD){
    338                 mainNetSwitch = true;
    339                 emit MainNetOnlineEvent(now, totalPledge);
    340             }
    341         }
    342     }
    343     
    344     // to get the pledge of participate for specified candidate
    345     function getPledgeFlow(address candidate, address participate) public view returns(uint){
    346         require(isCandidate(candidate));
    347         return candidateElection[candidate].election[participate];
    348     }
    349     
    350     // to get all supporters of the specified candidate
    351     function getSupportOfCandidate(address candidate) public view returns(address[]){
    352         require(isCandidate(candidate));
    353         return candidateElection[candidate].participates;
    354     }
    355     
    356     // get rank of candidate
    357     function ranking(address _candidate) public view returns(uint){
    358         require(isCandidate(_candidate));
    359         require(address(0) != _candidate);
    360         uint index;
    361         uint rank;
    362         for(index = 0; index < CandidateList.length; index++){
    363             if(isCandidate(_candidate)){
    364                 rank++;
    365                 if(_candidate == CandidateList[index]){
    366                     return rank;
    367                 }
    368             }
    369         }
    370     }
    371     
    372     // issue a election for candidate with some pledges
    373     function issueVote(address candidate, uint pledge) private {
    374         require(isCandidate(candidate));
    375         require(!isCandidate(msg.sender));
    376         require(pledge <= justitia.residePledge(msg.sender));
    377         
    378         if(!candidateElection[candidate].isValid){
    379             candidateElection[candidate].participates.push(msg.sender);
    380             candidateElection[candidate].isValid = true;
    381         }
    382         candidateLookup[candidate].pledge = candidateLookup[candidate].pledge.add(pledge);
    383         candidateElection[candidate].election[msg.sender] = candidateElection[candidate].election[msg.sender].add(pledge);
    384         adjustCandidateList(candidate, candidateLookup[candidate].pledge);
    385         balanceOfPledge[msg.sender] = balanceOfPledge[msg.sender].add(pledge);
    386         totalPledge = totalPledge.add(pledge);
    387         justitia.lockCount(msg.sender, pledge);
    388         
    389         emit IssueVoteEvent(msg.sender, candidate, pledge);
    390     }
    391     
    392     // to adjustment of voting for specified candidate with pledge
    393     function adjustmentVote(address candidate, uint pledge) private {
    394         require(isCandidate(candidate));
    395         require(pledge <= candidateElection[candidate].election[msg.sender]);
    396         
    397         candidateLookup[candidate].pledge = candidateLookup[candidate].pledge.sub(pledge);
    398         candidateElection[candidate].election[msg.sender] = candidateElection[candidate].election[msg.sender].sub(pledge);
    399         adjustCandidateList(candidate, candidateLookup[candidate].pledge);
    400         balanceOfPledge[msg.sender] = balanceOfPledge[msg.sender].sub(pledge);
    401         totalPledge = totalPledge.sub(pledge);
    402         justitia.unlockCount(msg.sender, pledge);
    403         
    404         emit AdjustmentVoteEvent(msg.sender, candidate, pledge);
    405     }
    406     
    407     function rightToVoteBlackList(address _account) private view returns(bool){
    408         require(isCandidate(_account));
    409         if(candidateLookup[_account].ranking < totalNodes){
    410             return true;
    411         }
    412         return false;
    413     }
    414     
    415     function GetOnlineSymbol() public view returns(bool){
    416         return mainNetSwitch;
    417     }
    418     
    419     function VoteAdjustment(address candidate, uint canceledPledge) public {
    420         require(isCandidate(candidate));
    421         adjustmentVote(candidate, canceledPledge);
    422     }
    423     
    424     function Votting(address candidate, uint pledge) public{
    425         require(isCandidate(candidate));
    426         issueVote(candidate, pledge);
    427         tryToOnlineMainNet();
    428     }
    429     
    430     function SetBlackList(address _account) public{
    431         require(rightToVoteBlackList(msg.sender));
    432         if(!isInBlackList(_account)){
    433             voteForBlacklist(_account, "errors");
    434         }
    435     }
    436 }
    View Code
  • 相关阅读:
    Ubuntu虚拟机磁盘空间不足的解决
    eclipse启动报错 JVM terminated. Exit code=1
    Ubuntu16.04 安装eclipse
    HDU 1710 Binary Tree Traversals(二叉树)
    Ubuntu16.04 搭建伪分布式Hadoop环境
    HDU 1560 DNA sequence(IDA*)
    Go的函数
    Go的包
    Go语言开发环境搭建
    go的循环
  • 原文地址:https://www.cnblogs.com/yunlion/p/10437333.html
Copyright © 2011-2022 走看看