github.com/vantum/vantum@v0.0.0-20180815184342-fe37d5f7a990/contracts/masternode/contract/masternode.sol (about)

     1  pragma solidity ^0.4.11;
     2  
     3  contract Masternode {
     4  
     5      uint public constant etzPerNode = 20 * 10 ** 18;
     6      uint public constant etzMin = 10 ** 16;
     7      uint public constant blockPingTimeout = 3600;
     8  
     9      bytes8 public lastId;
    10      uint public count;
    11  
    12      struct node {
    13          bytes32 id1;
    14          bytes32 id2;
    15          bytes8 preId;
    16          bytes8 nextId;
    17          address account;
    18          uint block;
    19  
    20          uint blockOnlineAcc;
    21          uint blockLastPing;
    22      }
    23  
    24      mapping (bytes8 => node) nodes;
    25      mapping (address => bytes8) ids;
    26      mapping (address => bytes8) nodeAddressToId;
    27  
    28      uint public constant proposalPeriod = 1200000;
    29      uint public constant proposalFee = 10 * 10 ** 18;
    30      address public governanceAddress;
    31      address public lastProposalAddress;
    32      struct vote {
    33          uint voteCount;
    34          uint startBlock;
    35          uint stopBlock;
    36          address creator;
    37          address lastAddress;
    38      }
    39  
    40      mapping(address => mapping(address => bool)) voters;
    41      mapping (address => vote) votes;
    42  
    43      event join(bytes8 id, address addr);
    44      event quit(bytes8 id, address addr);
    45      event ping(bytes8 id, uint blockOnlineAcc, uint blockLastPing);
    46  
    47      constructor() public {
    48          lastId = bytes8(0);
    49          count = 0;
    50      }
    51  
    52      function register(bytes32 id1, bytes32 id2) payable public {
    53          bytes8 id = bytes8(id1);
    54          require(
    55              bytes32(0) != id1 &&
    56              bytes32(0) != id2 &&
    57              bytes8(0) != id &&
    58              bytes8(0) == ids[msg.sender] &&
    59              bytes32(0) == nodes[id].id1 &&
    60              msg.value == etzPerNode
    61          );
    62          bytes32[2] memory input;
    63          bytes32[1] memory output;
    64          input[0] = id1;
    65          input[1] = id2;
    66          assembly {
    67              if iszero(call(not(0), 0x0b, 0, input, 128, output, 32)) {
    68                revert(0, 0)
    69              }
    70          }
    71          address account = address(output[0]);
    72          require(account != address(0));
    73  
    74          ids[msg.sender] = id;
    75          nodes[id] = node(
    76              id1,
    77              id2,
    78              lastId,
    79              bytes8(0),
    80              msg.sender,
    81              block.number,
    82              uint(0),
    83              uint(0)
    84          );
    85          if(lastId != bytes8(0)){
    86              nodes[lastId].nextId = id;
    87          }
    88          lastId = id;
    89          count += 1;
    90          nodeAddressToId[account] = id;
    91          account.transfer(etzMin);
    92          emit join(id, msg.sender);
    93      }
    94  
    95      function() payable public {
    96          require(msg.value == 0);
    97          bytes8 id = nodeAddressToId[msg.sender];
    98          if (id != bytes8(0) && has(id)){
    99              // ping
   100              uint blockLastPing = nodes[id].blockLastPing;
   101              if(blockLastPing > 0){
   102                  uint blockGap = block.number - blockLastPing;
   103                  if(blockGap > blockPingTimeout){
   104                      nodes[id].blockOnlineAcc = 0;
   105                  }else{
   106                      nodes[id].blockOnlineAcc += blockGap;
   107                  }
   108              }
   109              nodes[id].blockLastPing = block.number;
   110              emit ping(id, nodes[id].blockOnlineAcc, block.number);
   111          }else{
   112              id = ids[msg.sender];
   113              bytes32 id1 = nodes[id].id1;
   114              require(
   115                  msg.value == 0 &&
   116                  bytes8(0) != id &&
   117                  bytes32(0) != id1 &&
   118                  address(this).balance >= (etzPerNode - etzMin) &&
   119                  count > 0
   120              );
   121  
   122              bytes32[2] memory input;
   123              bytes32[1] memory output;
   124              input[0] = id1;
   125              input[1] = nodes[id].id2;
   126              assembly {
   127                  if iszero(call(not(0), 0x0b, 0, input, 128, output, 32)) {
   128                    revert(0, 0)
   129                  }
   130              }
   131              address account = address(output[0]);
   132              nodeAddressToId[account] = bytes8(0);
   133  
   134              bytes8 preId = nodes[id].preId;
   135              bytes8 nextId = nodes[id].nextId;
   136              if(preId != bytes8(0)){
   137                  nodes[preId].nextId = nextId;
   138              }
   139              if(nextId != bytes8(0)){
   140                  nodes[nextId].preId = preId;
   141              }else{
   142                  lastId = preId;
   143              }
   144              nodes[id] = node(
   145                  bytes32(0),
   146                  bytes32(0),
   147                  bytes8(0),
   148                  bytes8(0),
   149                  address(0),
   150                  uint(0),
   151                  uint(0),
   152                  uint(0)
   153              );
   154              ids[msg.sender] = bytes8(0);
   155              count -= 1;
   156              emit quit(id, msg.sender);
   157              msg.sender.transfer(etzPerNode - etzMin);
   158          }
   159  
   160      }
   161  
   162      function getInfo(bytes8 id) constant public returns (
   163          bytes32 id1,
   164          bytes32 id2,
   165          bytes8 preId,
   166          bytes8 nextId,
   167          uint blockNumber,
   168          address account,
   169          uint blockOnlineAcc,
   170          uint blockLastPing
   171      )
   172      {
   173          id1 = nodes[id].id1;
   174          id2 = nodes[id].id2;
   175          preId = nodes[id].preId;
   176          nextId = nodes[id].nextId;
   177          blockNumber = nodes[id].block;
   178          account = nodes[id].account;
   179          blockOnlineAcc = nodes[id].blockOnlineAcc;
   180          blockLastPing = nodes[id].blockLastPing;
   181      }
   182  
   183      function getId(address addr) constant public returns (bytes8 id)
   184      {
   185          id = ids[addr];
   186      }
   187  
   188      function has(bytes8 id) constant public returns (bool)
   189      {
   190          return nodes[id].id1 != bytes32(0);
   191      }
   192  
   193      function createGovernanceAddressVote(address addr) payable public
   194      {
   195          require(votes[addr].voteCount == 0
   196          && votes[addr].startBlock == 0
   197          && msg.value == proposalFee);
   198          votes[addr] = vote({
   199              voteCount: 0,
   200              startBlock: block.number,
   201              stopBlock: block.number + proposalPeriod,
   202              creator: msg.sender,
   203              lastAddress: lastProposalAddress
   204          });
   205          lastProposalAddress = addr;
   206      }
   207  
   208      function voteForGovernanceAddress(address addr) public
   209      {
   210          vote storage v = votes[addr];
   211          bytes8 id = getId(msg.sender);
   212          require(v.startBlock > 0
   213          && block.number > v.startBlock
   214          && block.number < v.stopBlock
   215          && id != bytes8(0)
   216          && (block.number - nodes[id].block) > proposalPeriod
   217          && voters[addr][msg.sender] == false);
   218          voters[addr][msg.sender] = true;
   219          v.voteCount += 1;
   220          if (v.voteCount > (count / 2))
   221          {
   222              v.stopBlock = block.number;
   223              governanceAddress = addr;
   224          }
   225      }
   226  
   227      function getVoteInfo(address addr) constant public returns (
   228          uint voteCount,
   229          uint startBlock,
   230          uint stopBlock,
   231          address creator,
   232          address lastAddress
   233      )
   234      {
   235          voteCount = votes[addr].voteCount;
   236          startBlock = votes[addr].startBlock;
   237          stopBlock = votes[addr].stopBlock;
   238          creator = votes[addr].creator;
   239          lastAddress = votes[addr].lastAddress;
   240      }
   241  }