github.com/inklabsfoundation/inkchain@v0.17.1-0.20181025012015-c3cef8062f19/examples/xc/qtum/contracts/XCPlugin.sol (about)

     1  pragma solidity ^0.4.19;
     2  
     3  import "./XCPluginInterface.sol";
     4  
     5  contract XCPlugin is XCPluginInterface {
     6  
     7      /**
     8       * Contract Administrator
     9       * @field status Contract external service status.
    10       * @field platformName Current contract platform name.
    11       * @field account Current contract administrator.
    12       */
    13      struct Admin {
    14  
    15          bool status;
    16  
    17          bytes32 platformName;
    18  
    19          address account;
    20      }
    21  
    22      /**
    23       * Transaction Proposal
    24       * @field status Transaction proposal status(false:pending,true:complete).
    25       * @field fromAccount Account of form platform.
    26       * @field toAccount Account of to platform.
    27       * @field value Transfer amount.
    28       * @field voters Proposers.
    29       * @field weight The weight value of the completed time.
    30       */
    31      struct Proposal {
    32  
    33          bool status;
    34  
    35          address fromAccount;
    36  
    37          address toAccount;
    38  
    39          uint value;
    40  
    41          address[] voters;
    42  
    43          uint weight;
    44      }
    45  
    46      /**
    47       * Trusted Platform
    48       * @field status Trusted platform state(false:no trusted,true:trusted).
    49       * @field weight weight of platform.
    50       * @field publicKeys list of public key.
    51       * @field proposals list of proposal.
    52       */
    53      struct Platform {
    54  
    55          bool status;
    56  
    57          uint weight;
    58  
    59          address[] publicKeys;
    60  
    61          mapping(string => Proposal) proposals;
    62      }
    63  
    64      Admin private admin;
    65  
    66      address[] private callers;
    67  
    68      mapping(bytes32 => Platform) private platforms;
    69  
    70      function XCPlugin() public {
    71          //TODO
    72          bytes32 name = "QTUM";
    73  
    74          admin = Admin(false, name, msg.sender);
    75      }
    76  
    77      function start() external {
    78  
    79          require(admin.account == msg.sender);
    80  
    81          if (!admin.status) {
    82  
    83              admin.status = true;
    84          }
    85      }
    86  
    87      function stop() external {
    88  
    89          require(admin.account == msg.sender);
    90  
    91          if (admin.status) {
    92  
    93              admin.status = false;
    94          }
    95      }
    96  
    97      function getStatus() external view returns (bool) {
    98  
    99          return admin.status;
   100      }
   101  
   102      function setPlatformName(bytes32 platformName) external {
   103  
   104          require(admin.account == msg.sender);
   105  
   106          if (admin.platformName != platformName) {
   107  
   108              admin.platformName = platformName;
   109          }
   110      }
   111  
   112      function getPlatformName() external view returns (bytes32) {
   113  
   114          return admin.platformName;
   115      }
   116  
   117      function setAdmin(address account) external {
   118  
   119          require(account != address(0));
   120  
   121          require(admin.account == msg.sender);
   122  
   123          if (admin.account != account) {
   124  
   125              admin.account = account;
   126          }
   127      }
   128  
   129      function getAdmin() external view returns (address) {
   130  
   131          return admin.account;
   132      }
   133  
   134      function addCaller(address caller) external {
   135  
   136          require(admin.account == msg.sender);
   137  
   138          if (!_existCaller(caller)) {
   139  
   140              callers.push(caller);
   141          }
   142      }
   143  
   144      function deleteCaller(address caller) external {
   145  
   146          require(admin.account == msg.sender);
   147  
   148          if (_existCaller(caller)) {
   149  
   150              bool exist;
   151  
   152              for (uint i = 0; i <= callers.length; i++) {
   153  
   154                  if (exist) {
   155  
   156                      if (i == callers.length) {
   157  
   158                          delete callers[i - 1];
   159  
   160                          callers.length--;
   161                      } else {
   162  
   163                          callers[i - 1] = callers[i];
   164                      }
   165                  } else if (callers[i] == caller) {
   166  
   167                      exist = true;
   168                  }
   169              }
   170  
   171          }
   172      }
   173  
   174      function existCaller(address caller) external view returns (bool) {
   175  
   176          return _existCaller(caller);
   177      }
   178  
   179  
   180      function _existCaller(address caller) internal view returns (bool) {
   181  
   182          for (uint i = 0; i < callers.length; i++) {
   183  
   184              if (callers[i] == caller) {
   185  
   186                  return true;
   187              }
   188          }
   189  
   190          return false;
   191      }
   192  
   193      function getCallers() external view returns (address[]) {
   194  
   195          require(admin.account == msg.sender);
   196  
   197          return callers;
   198      }
   199  
   200      function addPlatform(bytes32 name) external {
   201  
   202          require(admin.account == msg.sender);
   203  
   204          require(name != "");
   205  
   206          require(name != admin.platformName);
   207  
   208          if (!_existPlatform(name)) {
   209  
   210              platforms[name].status = true;
   211  
   212              if (platforms[name].weight == 0) {
   213  
   214                  platforms[name].weight = 1;
   215              }
   216          }
   217      }
   218  
   219      function deletePlatform(bytes32 name) external {
   220  
   221          require(admin.account == msg.sender);
   222  
   223          require(name != admin.platformName);
   224  
   225          if (_existPlatform(name)) {
   226  
   227              platforms[name].status = false;
   228          }
   229      }
   230  
   231      function existPlatform(bytes32 name) external view returns (bool){
   232  
   233          return _existPlatform(name);
   234      }
   235  
   236      function _existPlatform(bytes32 name) internal view returns (bool){
   237  
   238          return platforms[name].status;
   239      }
   240  
   241      function setWeight(bytes32 platformName, uint weight) external {
   242  
   243          require(admin.account == msg.sender);
   244  
   245          require(_existPlatform(platformName));
   246  
   247          require(weight > 0);
   248  
   249          if (platforms[platformName].weight != weight) {
   250  
   251              platforms[platformName].weight = weight;
   252          }
   253      }
   254  
   255      function getWeight(bytes32 platformName) external view returns (uint) {
   256  
   257          require(admin.account == msg.sender);
   258  
   259          require(_existPlatform(platformName));
   260  
   261          return platforms[platformName].weight;
   262      }
   263  
   264      function addPublicKey(bytes32 platformName, address publicKey) external {
   265  
   266          require(admin.account == msg.sender);
   267  
   268          require(_existPlatform(platformName));
   269  
   270          require(publicKey != address(0));
   271  
   272          address[] storage listOfPublicKey = platforms[platformName].publicKeys;
   273  
   274          for (uint i; i < listOfPublicKey.length; i++) {
   275  
   276              if (publicKey == listOfPublicKey[i]) {
   277  
   278                  return;
   279              }
   280          }
   281  
   282          listOfPublicKey.push(publicKey);
   283      }
   284  
   285      function deletePublicKey(bytes32 platformName, address publickey) external {
   286  
   287          require(admin.account == msg.sender);
   288  
   289          require(_existPlatform(platformName));
   290  
   291          address[] storage listOfPublicKey = platforms[platformName].publicKeys;
   292  
   293          bool exist;
   294  
   295          for (uint i = 0; i <= listOfPublicKey.length; i++) {
   296  
   297              if (exist) {
   298                  if (i == listOfPublicKey.length) {
   299  
   300                      delete listOfPublicKey[i - 1];
   301  
   302                      listOfPublicKey.length--;
   303                  } else {
   304  
   305                      listOfPublicKey[i - 1] = listOfPublicKey[i];
   306                  }
   307              } else if (listOfPublicKey[i] == publickey) {
   308  
   309                  exist = true;
   310              }
   311          }
   312      }
   313  
   314      function existPublicKey(bytes32 platformName, address publicKey) external view returns (bool) {
   315  
   316          require(admin.account == msg.sender);
   317  
   318          return _existPublicKey(platformName, publicKey);
   319      }
   320  
   321      function _existPublicKey(bytes32 platformName, address publicKey) internal view returns (bool) {
   322  
   323  
   324          address[] memory listOfPublicKey = platforms[platformName].publicKeys;
   325  
   326          for (uint i = 0; i < listOfPublicKey.length; i++) {
   327  
   328              if (listOfPublicKey[i] == publicKey) {
   329  
   330                  return true;
   331              }
   332          }
   333  
   334          return false;
   335      }
   336  
   337      function countOfPublicKey(bytes32 platformName) external view returns (uint){
   338  
   339          require(admin.account == msg.sender);
   340  
   341          require(_existPlatform(platformName));
   342  
   343          return platforms[platformName].publicKeys.length;
   344      }
   345  
   346      function publicKeys(bytes32 platformName) external view returns (address[]){
   347  
   348          require(admin.account == msg.sender);
   349  
   350          require(_existPlatform(platformName));
   351  
   352          return platforms[platformName].publicKeys;
   353      }
   354  
   355      function voteProposal(bytes32 fromPlatform, address fromAccount, address toAccount, uint value, string txid, bytes32 r, bytes32 s, uint8 v) external {
   356  
   357          require(admin.status);
   358  
   359          require(_existPlatform(fromPlatform));
   360  
   361          bytes32 msgHash = hashMsg(fromPlatform, fromAccount, admin.platformName, toAccount, value, txid);
   362  
   363          address publicKey = ecrecover(msgHash, v, r, s);
   364  
   365          require(_existPublicKey(fromPlatform, publicKey));
   366  
   367          Proposal storage proposal = platforms[fromPlatform].proposals[txid];
   368  
   369          if (proposal.value == 0) {
   370  
   371              proposal.fromAccount = fromAccount;
   372  
   373              proposal.toAccount = toAccount;
   374  
   375              proposal.value = value;
   376          } else {
   377  
   378              require(proposal.fromAccount == fromAccount && proposal.toAccount == toAccount && proposal.value == value);
   379          }
   380  
   381          changeVoters(fromPlatform, publicKey, txid);
   382      }
   383  
   384      function verifyProposal(bytes32 fromPlatform, address fromAccount, address toAccount, uint value, string txid) external view returns (bool, bool) {
   385  
   386          require(admin.status);
   387  
   388          require(_existPlatform(fromPlatform));
   389  
   390          Proposal storage proposal = platforms[fromPlatform].proposals[txid];
   391  
   392          if (proposal.status) {
   393  
   394              return (true, (proposal.voters.length >= proposal.weight));
   395          }
   396  
   397          if (proposal.value == 0) {
   398  
   399              return (false, false);
   400          }
   401  
   402          require(proposal.fromAccount == fromAccount && proposal.toAccount == toAccount && proposal.value == value);
   403  
   404          return (false, (proposal.voters.length >= platforms[fromPlatform].weight));
   405      }
   406  
   407      function commitProposal(bytes32 platformName, string txid) external returns (bool) {
   408  
   409          require(admin.status);
   410  
   411          require(_existCaller(msg.sender) || msg.sender == admin.account);
   412  
   413          require(_existPlatform(platformName));
   414  
   415          require(!platforms[platformName].proposals[txid].status);
   416  
   417          platforms[platformName].proposals[txid].status = true;
   418  
   419          platforms[platformName].proposals[txid].weight = platforms[platformName].proposals[txid].voters.length;
   420  
   421          return true;
   422      }
   423  
   424      function getProposal(bytes32 platformName, string txid) external view returns (bool status, address fromAccount, address toAccount, uint value, address[] voters, uint weight){
   425  
   426          require(admin.status);
   427  
   428          require(_existPlatform(platformName));
   429  
   430          fromAccount = platforms[platformName].proposals[txid].fromAccount;
   431  
   432          toAccount = platforms[platformName].proposals[txid].toAccount;
   433  
   434          value = platforms[platformName].proposals[txid].value;
   435  
   436          voters = platforms[platformName].proposals[txid].voters;
   437  
   438          status = platforms[platformName].proposals[txid].status;
   439  
   440          weight = platforms[platformName].proposals[txid].weight;
   441  
   442          return;
   443      }
   444  
   445      function deleteProposal(bytes32 platformName, string txid) external {
   446  
   447          require(msg.sender == admin.account);
   448  
   449          require(_existPlatform(platformName));
   450  
   451          delete platforms[platformName].proposals[txid];
   452      }
   453  
   454      function transfer(address account, uint value) external payable {
   455  
   456          require(admin.account == msg.sender);
   457  
   458          require(account != address(0));
   459  
   460          require(value > 0 && value >= this.balance);
   461  
   462          this.transfer(account, value);
   463      }
   464  
   465      /**
   466       *   ######################
   467       *  #  private function  #
   468       * ######################
   469       */
   470  
   471      function hashMsg(bytes32 fromPlatform, address fromAccount, bytes32 toPlatform, address toAccount, uint value, string txid) internal pure returns (bytes32) {
   472  
   473          return sha256(bytes32ToStr(fromPlatform), ":0x", uintToStr(uint160(fromAccount), 16), ":", bytes32ToStr(toPlatform), ":0x", uintToStr(uint160(toAccount), 16), ":", uintToStr(value, 10), ":", txid);
   474      }
   475  
   476      function changeVoters(bytes32 platformName, address publicKey, string txid) internal {
   477  
   478          address[] storage voters = platforms[platformName].proposals[txid].voters;
   479  
   480          bool change = true;
   481  
   482          for (uint i = 0; i < voters.length; i++) {
   483  
   484              if (voters[i] == publicKey) {
   485  
   486                  change = false;
   487              }
   488          }
   489  
   490          if (change) {
   491  
   492              voters.push(publicKey);
   493          }
   494      }
   495  
   496      function bytes32ToBytes(bytes32 b) internal pure returns (bytes) {
   497  
   498          uint length = b.length;
   499  
   500          for (uint i = 0; i < b.length; i++) {
   501  
   502              if (b[b.length - 1 - i] == "") {
   503  
   504                  length -= 1;
   505              } else {
   506  
   507                  break;
   508              }
   509          }
   510  
   511          bytes memory bs = new bytes(length);
   512  
   513          for (uint j = 0; j < length; j++) {
   514  
   515              bs[j] = b[j];
   516          }
   517  
   518          return bs;
   519      }
   520  
   521      function bytes32ToStr(bytes32 b) internal pure returns (string) {
   522  
   523          bytes memory bs = bytes32ToBytes(b);
   524  
   525          return string(bs);
   526      }
   527  
   528      function uintToStr(uint value, uint base) internal pure returns (string) {
   529  
   530          uint _value = value;
   531  
   532          uint length = 0;
   533  
   534          bytes16 tenStr = "0123456789abcdef";
   535  
   536          while (true) {
   537  
   538              if (_value > 0) {
   539  
   540                  length ++;
   541  
   542                  _value = _value / base;
   543              } else {
   544  
   545                  break;
   546              }
   547          }
   548  
   549          if (base == 16) {
   550              length = 40;
   551          }
   552  
   553          bytes memory bs = new bytes(length);
   554  
   555          for (uint i = 0; i < length; i++) {
   556  
   557              bs[length - 1 - i] = tenStr[value % base];
   558  
   559              value = value / base;
   560          }
   561  
   562          return string(bs);
   563      }
   564  
   565  }