github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/contracts/chief/src/chief_1.0.0.sol (about)

     1  pragma solidity >=0.5.0 <=0.5.3;
     2  
     3  /* for remix
     4  import "github.com/SmartMeshFoundation/Spectrum/contracts/chief/src/chief_abs_s0.5.sol"; // for remix
     5  import "github.com/SmartMeshFoundation/Spectrum/contracts/chief/src/chief_base_s0.5_v0.0.1.sol"; // for remix
     6  */
     7  
     8  
     9  /* local */
    10  import "./chief_abs_s0.5.sol";
    11  import "./chief_base_s0.5_v0.0.1.sol";
    12  
    13  /*
    14  ----------
    15  | devnet |
    16  ----------   
    17  
    18  test nodes :
    19  
    20      leader :
    21  
    22          privatekey: 507fd083b5c5af7e645e77a3a3a82708f3af304164e02612ab4b1d5b36c627c6
    23          address: 0x9944d0cc757cd9391ee320fc17d5b6f61693f2c5
    24  
    25      deposit :
    26  
    27          privatekey: 543e9d0ddcd02b4bbdb2cecd402da99e9532fface57d8ea74e833c5d413f2daa
    28          address: 0xd3F50Dfd2887B3818aB9E6c6f846ED1d3bD90B29
    29  
    30          privatekey: 9d7b3b8155ea429cb49cdc556aa7b3367feb91ccf51eb1e9c7e2bac67d939f03
    31          address: 0x50bf23F1d844465AB69357aa08Af0fEA4B1E62D7
    32  
    33  
    34  
    35  f = "0xbf1736a65f8beadd71b321be585fd883503fdeaa"; personal.unlockAccount(f,"123456")
    36  
    37      sign(f):
    38  
    39          addr: 0xd3F50Dfd2887B3818aB9E6c6f846ED1d3bD90B29
    40          R: 0x99b087c99fceee44b15373847e38f485b31b5b779ce7b01081f2d61c00c77d19
    41          S: 0x0f29d84ff759415e969e12a49cf2fc453c1b2aa386d59e0488b11627dcdbd261
    42          V: 27 
    43  
    44          addr: 0x50bf23F1d844465AB69357aa08Af0fEA4B1E62D7
    45          R: 0x2edbf406a13757485096ae35d85f1f881f17073e230454ad83a65e003ff2deb8
    46          S: 0x4629840c12909009ad4092f8da67d53b57a7a2c8fa6abe024166982d65821fcb
    47          V: 27
    48  
    49  
    50  ChiefBase : 0xad61f1201f592fbf13d2645f9c59d8d5f82a1837 //
    51      deploy args : 25,5
    52      appendLeader args : "0x9944d0cc757cd9391ee320fc17d5b6f61693f2c5"
    53  
    54  POC : 0x901c0636c4fc83f353bca2db85e2ace886a9416d
    55      deploy args : "0xad61f1201f592fbf13d2645f9c59d8d5f82a1837",10,10,50
    56      deposit args :
    57          "0x99b087c99fceee44b15373847e38f485b31b5b779ce7b01081f2d61c00c77d19","0x0f29d84ff759415e969e12a49cf2fc453c1b2aa386d59e0488b11627dcdbd261",27
    58          "0x2edbf406a13757485096ae35d85f1f881f17073e230454ad83a65e003ff2deb8","0x4629840c12909009ad4092f8da67d53b57a7a2c8fa6abe024166982d65821fcb",27
    59  
    60  
    61  Tribe : 0x6d05f6aa4e19e20cd781fa3def97bbfd0b980534
    62      deploy args : "0xad61f1201f592fbf13d2645f9c59d8d5f82a1837","0x901c0636c4fc83f353bca2db85e2ace886a9416d"
    63  
    64  */
    65  
    66  contract TribeChief_1_0_0 is Chief {
    67  
    68      string vsn = "1.0.0";
    69  
    70      struct BlackMember {
    71          address addr;
    72          uint score;
    73          uint number;
    74      }
    75  
    76      ChiefBase_1_0_0 private base;
    77  
    78  
    79      address[] public  _signerList; //当前轮的17块的出块人列表(包含Leader)
    80      address[] public  _nextRoundSignerList; //下一轮17块出块人列表,不包含Leader
    81      uint  public  blockNumber; //当前块
    82  
    83  
    84  
    85      // the mapping of the signer score and the block number
    86      mapping(address => uint)   signersMap; //标记某个地址在当前轮中是否是signer
    87  
    88      constructor(address baseAddress, address pocAddress,uint startBlockNumber) public {
    89          base = ChiefBase_1_0_0(baseAddress);
    90          base.init(pocAddress, address(this));
    91          blockNumber=startBlockNumber; //从此块开始分叉
    92  
    93          address[] memory leaderList = base.takeLeaderList();
    94          require(leaderList.length > 0);
    95  
    96          signersMap[leaderList[0]] = 1;
    97          _signerList.push(leaderList[0]);
    98  
    99          for (uint i = _signerList.length; i < base.takeSignerLimit(); i++) {
   100              // placeholder
   101              _signerList.push(address(0));
   102          }
   103  
   104      }
   105  
   106      modifier allow() {
   107          address _addr = msg.sender;
   108          require(uint160(_addr) != uint160(0));
   109          require(signersMap[_addr] > 0 || base.isLeader(_addr));
   110          _;
   111      }
   112  
   113      function pushNextRoundSigner(address addr)  private {
   114          if (_nextRoundSignerList.length < base.takeVolunteerLimit()) {
   115              _nextRoundSignerList.push(addr);
   116          } else{
   117              //            revert("next round signer too much");
   118          }
   119      }
   120  
   121      // append a signer
   122      function pushSigner(address signer ) private {
   123          if (_signerList.length < base.takeSignerLimit()) {
   124              _signerList.push(signer);
   125              signersMap[signer] = 1;
   126          } else{
   127              //            revert("too many signer");
   128          }
   129      }
   130  
   131      // clean all of list and return _signerList[0]
   132      function clean_all_signer_and_get0()  private returns (address) {
   133          address signer0=_signerList[0]; //至少会有一个signer
   134          // clean all of signerList
   135          for (uint i = 0;i<_signerList.length;i++) {
   136              signersMap[_signerList[i]]=0;
   137              _signerList[i]=address(0);
   138          }
   139          _signerList.length=0;
   140          return signer0;
   141      }
   142  
   143      function genSigners_set_leader(address signer0 ) private {
   144          address[] memory leaders = base.takeLeaderList();
   145          for (uint i = 0; i < leaders.length; i++) {
   146              address l = leaders[i];
   147              if (signer0 == l) {
   148                  if (i == leaders.length - 1) {
   149                      pushSigner(leaders[0]);
   150                  } else {
   151                      pushSigner(leaders[i + 1]);
   152                  }
   153                  return;
   154              }
   155          }
   156          //        revert("signer0 must exist in leader list");
   157          /*
   158          there must at least one leader.
   159          current leader maybe removed.
   160          */
   161          pushSigner(leaders[0]);
   162      }
   163  
   164      // push volunteerList to signerList
   165      function genSigners_v2s() private {
   166          for (uint i = 0; i < _nextRoundSignerList.length; i++) {
   167              address v = _nextRoundSignerList[i];
   168              pushSigner(v);
   169          }
   170          for (uint i = _signerList.length; i < base.takeSignerLimit(); i++) {
   171              // placeholder
   172              _signerList.push(address(0));
   173          }
   174      }
   175  
   176      // clean volunteerList
   177      function genSigners_clean_next_round_signers() private {
   178          for (uint i =0; i< _nextRoundSignerList.length; i++) {
   179              _nextRoundSignerList[i]=address(0);
   180          }
   181          _nextRoundSignerList.length=0;
   182      }
   183  
   184      function genSigners_clean_blackList() private {
   185          base.pocCleanBlackList();
   186      }
   187  
   188      function genSigners() private  {
   189          address signer0=clean_all_signer_and_get0();
   190          require(signer0!=address(0),"signer0 must not be zero");
   191          // generate
   192          genSigners_set_leader(signer0);
   193          // move next round candidate signers to current signer list
   194          genSigners_v2s();
   195          // clear next round candidate signers.
   196          genSigners_clean_next_round_signers();
   197      }
   198      //合约外部调用唯一的入口
   199      function update(address volunteer) public allow() {
   200  
   201          blockNumber = block.number;
   202  
   203          uint l = base.takeSignerLimit();
   204          uint signerIdx = uint(blockNumber % l); //轮到signerIdx出块
   205          address si = _signerList[signerIdx];
   206  
   207          //1 : not leader signer, and `sender!=si` move `si` to waitList in POC contract
   208          if (signerIdx > uint(0)) { //leader不是选出来的
   209  
   210              if (uint160(volunteer) != uint160(0)) {
   211                  pushNextRoundSigner(volunteer);
   212              }
   213              //轮到si出块,si没有,那么会惩罚si
   214              if (si != address(0) && msg.sender != si) {
   215                  // move si to stopList in POC contract
   216                  if (base.pocAddStop(si) > 0) {
   217                      // move to blackList
   218                      base.pocAddBlackList(si);
   219                  }
   220                  delete signersMap[si];
   221                  // mark 0  
   222                  _signerList[signerIdx] = address(0);
   223              }
   224          }
   225  
   226          //2 : last block, reset signerList
   227          if (signerIdx == (l - 1)) {
   228              genSigners(); //一轮结束,选择下一轮出块人
   229          }
   230          //拉黑持续时间为一个epoch
   231          if (block.number%getEpoch()==0){
   232              // clean blackList
   233              genSigners_clean_blackList();
   234          }
   235      }
   236  
   237      function getStatus() public view returns (
   238      //address[] volunteerList,
   239          address[] memory signerList,
   240          address[] memory blackList, // vsn 0.0.3
   241          uint[] memory scoreList,
   242          uint[] memory numberList,
   243          uint totalVolunteer,
   244          uint number
   245      ) {
   246          scoreList = new uint[](_signerList.length);
   247          numberList = new uint[](_signerList.length);
   248          for (uint i = 0; i < _signerList.length; i ++) {
   249              scoreList[i] = 0;
   250              numberList[i] = signersMap[_signerList[i]];
   251          }
   252          // TODO
   253          blackList = base.pocGetBlackList();
   254  
   255          signerList = _signerList;
   256          // vsn 0.0.3
   257          number = blockNumber;
   258          totalVolunteer = _nextRoundSignerList.length;
   259      }
   260  
   261      function version() public view returns (string memory) {return vsn;}
   262  
   263      function getSignerLimit() public view returns (uint) {return base.takeSignerLimit();}
   264  
   265      function getEpoch() public view returns (uint) {return base.takeEpoch();}
   266  
   267      function getVolunteerLimit() public view returns (uint) {return base.takeVolunteerLimit();}
   268      //为了保持兼容性,所以名字保持不变
   269      function getVolunteers() public view returns (
   270          address[] memory volunteerList,
   271          uint[] memory weightList,
   272          uint length
   273      ){
   274          (volunteerList,length)=getNextRoundSignerList();
   275          weightList = new uint[](length);
   276      }
   277      function getNextRoundSignerList() public view returns (
   278          address[] memory nextRoundSignerList,
   279          uint length
   280      ) {
   281          nextRoundSignerList=_nextRoundSignerList;
   282          length=nextRoundSignerList.length;
   283      }
   284  
   285      // TODO
   286      function filterVolunteer(address[] memory volunteers) public view returns (uint[] memory result) {}
   287      //    function test_update(address nextsigner) public{
   288      //        update(nextsigner);
   289      //    }
   290      //    function test_push_signer(uint256 i,address signer) public{
   291      //            _signerList[i]=signer;
   292      //            signersMap[signer] = 1;
   293      //    }
   294  }
   295