github.com/inklabsfoundation/inkchain@v0.17.1-0.20181025012015-c3cef8062f19/examples/xc/eth/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 = "ETH";
    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      function _existCaller(address caller) internal view returns (bool) {
   180  
   181          for (uint i = 0; i < callers.length; i++) {
   182  
   183              if (callers[i] == caller) {
   184  
   185                  return true;
   186              }
   187          }
   188  
   189          return false;
   190      }
   191  
   192      function getCallers() external view returns (address[]) {
   193  
   194          require(admin.account == msg.sender);
   195  
   196          return callers;
   197      }
   198  
   199      function addPlatform(bytes32 name) external {
   200  
   201          require(admin.account == msg.sender);
   202  
   203          require(name != "");
   204  
   205          require(name != admin.platformName);
   206  
   207          if (!_existPlatform(name)) {
   208  
   209              platforms[name].status = true;
   210  
   211              if (platforms[name].weight == 0) {
   212  
   213                  platforms[name].weight = 1;
   214              }
   215          }
   216      }
   217  
   218      function deletePlatform(bytes32 name) external {
   219  
   220          require(admin.account == msg.sender);
   221  
   222          require(name != admin.platformName);
   223  
   224          if (_existPlatform(name)) {
   225  
   226              platforms[name].status = false;
   227          }
   228      }
   229  
   230      function existPlatform(bytes32 name) external view returns (bool){
   231  
   232          return _existPlatform(name);
   233      }
   234  
   235      function _existPlatform(bytes32 name) internal view returns (bool){
   236  
   237          return platforms[name].status;
   238      }
   239  
   240      function setWeight(bytes32 platformName, uint weight) external {
   241  
   242          require(admin.account == msg.sender);
   243  
   244          require(_existPlatform(platformName));
   245  
   246          require(weight > 0);
   247  
   248          if (platforms[platformName].weight != weight) {
   249  
   250              platforms[platformName].weight = weight;
   251          }
   252      }
   253  
   254      function getWeight(bytes32 platformName) external view returns (uint) {
   255  
   256          require(admin.account == msg.sender);
   257  
   258          require(_existPlatform(platformName));
   259  
   260          return platforms[platformName].weight;
   261      }
   262  
   263      function addPublicKey(bytes32 platformName, address publicKey) external {
   264  
   265          require(admin.account == msg.sender);
   266  
   267          require(_existPlatform(platformName));
   268  
   269          require(publicKey != address(0));
   270  
   271          address[] storage listOfPublicKey = platforms[platformName].publicKeys;
   272  
   273          for (uint i; i < listOfPublicKey.length; i++) {
   274  
   275              if (publicKey == listOfPublicKey[i]) {
   276  
   277                  return;
   278              }
   279          }
   280  
   281          listOfPublicKey.push(publicKey);
   282      }
   283  
   284      function deletePublicKey(bytes32 platformName, address publickey) external {
   285  
   286          require(admin.account == msg.sender);
   287  
   288          require(_existPlatform(platformName));
   289  
   290          address[] storage listOfPublicKey = platforms[platformName].publicKeys;
   291  
   292          bool exist;
   293  
   294          for (uint i = 0; i <= listOfPublicKey.length; i++) {
   295  
   296              if (exist) {
   297                  if (i == listOfPublicKey.length) {
   298  
   299                      delete listOfPublicKey[i - 1];
   300  
   301                      listOfPublicKey.length--;
   302                  } else {
   303  
   304                      listOfPublicKey[i - 1] = listOfPublicKey[i];
   305                  }
   306              } else if (listOfPublicKey[i] == publickey) {
   307  
   308                  exist = true;
   309              }
   310          }
   311      }
   312  
   313      function existPublicKey(bytes32 platformName, address publicKey) external view returns (bool) {
   314  
   315          require(admin.account == msg.sender);
   316  
   317          return _existPublicKey(platformName, publicKey);
   318      }
   319  
   320      function _existPublicKey(bytes32 platformName, address publicKey) internal view returns (bool) {
   321  
   322          address[] memory listOfPublicKey = platforms[platformName].publicKeys;
   323  
   324          for (uint i = 0; i < listOfPublicKey.length; i++) {
   325  
   326              if (listOfPublicKey[i] == publicKey) {
   327  
   328                  return true;
   329              }
   330          }
   331  
   332          return false;
   333      }
   334  
   335      function countOfPublicKey(bytes32 platformName) external view returns (uint){
   336  
   337          require(admin.account == msg.sender);
   338  
   339          require(_existPlatform(platformName));
   340  
   341          return platforms[platformName].publicKeys.length;
   342      }
   343  
   344      function publicKeys(bytes32 platformName) external view returns (address[]){
   345  
   346          require(admin.account == msg.sender);
   347  
   348          require(_existPlatform(platformName));
   349  
   350          return platforms[platformName].publicKeys;
   351      }
   352  
   353      function voteProposal(bytes32 fromPlatform, address fromAccount, address toAccount, uint value, string txid, bytes32 r, bytes32 s, uint8 v) external {
   354  
   355          require(admin.status);
   356  
   357          require(_existPlatform(fromPlatform));
   358  
   359          bytes32 msgHash = hashMsg(fromPlatform, fromAccount, admin.platformName, toAccount, value, txid);
   360  
   361          address publicKey = ecrecover(msgHash, v, r, s);
   362  
   363          require(_existPublicKey(fromPlatform, publicKey));
   364  
   365          Proposal storage proposal = platforms[fromPlatform].proposals[txid];
   366  
   367          if (proposal.value == 0) {
   368  
   369              proposal.fromAccount = fromAccount;
   370  
   371              proposal.toAccount = toAccount;
   372  
   373              proposal.value = value;
   374          } else {
   375  
   376              require(proposal.fromAccount == fromAccount && proposal.toAccount == toAccount && proposal.value == value);
   377          }
   378  
   379          changeVoters(fromPlatform, publicKey, txid);
   380      }
   381  
   382      function verifyProposal(bytes32 fromPlatform, address fromAccount, address toAccount, uint value, string txid) external view returns (bool, bool) {
   383  
   384          require(admin.status);
   385  
   386          require(_existPlatform(fromPlatform));
   387  
   388          Proposal storage proposal = platforms[fromPlatform].proposals[txid];
   389  
   390          if (proposal.status) {
   391  
   392              return (true, (proposal.voters.length >= proposal.weight));
   393          }
   394  
   395          if (proposal.value == 0) {
   396  
   397              return (false, false);
   398          }
   399  
   400          require(proposal.fromAccount == fromAccount && proposal.toAccount == toAccount && proposal.value == value);
   401  
   402          return (false, (proposal.voters.length >= platforms[fromPlatform].weight));
   403      }
   404  
   405      function commitProposal(bytes32 platformName, string txid) external returns (bool) {
   406  
   407          require(admin.status);
   408  
   409          require(_existCaller(msg.sender) || msg.sender == admin.account);
   410  
   411          require(_existPlatform(platformName));
   412  
   413          require(!platforms[platformName].proposals[txid].status);
   414  
   415          platforms[platformName].proposals[txid].status = true;
   416  
   417          platforms[platformName].proposals[txid].weight = platforms[platformName].proposals[txid].voters.length;
   418  
   419          return true;
   420      }
   421  
   422      function getProposal(bytes32 platformName, string txid) external view returns (bool status, address fromAccount, address toAccount, uint value, address[] voters, uint weight){
   423  
   424          require(admin.status);
   425  
   426          require(_existPlatform(platformName));
   427  
   428          fromAccount = platforms[platformName].proposals[txid].fromAccount;
   429  
   430          toAccount = platforms[platformName].proposals[txid].toAccount;
   431  
   432          value = platforms[platformName].proposals[txid].value;
   433  
   434          voters = platforms[platformName].proposals[txid].voters;
   435  
   436          status = platforms[platformName].proposals[txid].status;
   437  
   438          weight = platforms[platformName].proposals[txid].weight;
   439  
   440          return;
   441      }
   442  
   443      function deleteProposal(bytes32 platformName, string txid) external {
   444  
   445          require(msg.sender == admin.account);
   446  
   447          require(_existPlatform(platformName));
   448  
   449          delete platforms[platformName].proposals[txid];
   450      }
   451  
   452      function transfer(address account, uint value) external payable {
   453  
   454          require(admin.account == msg.sender);
   455  
   456          require(account != address(0));
   457  
   458          require(value > 0 && value >= this.balance);
   459  
   460          this.transfer(account, value);
   461      }
   462  
   463      /**
   464       *   ######################
   465       *  #  private function  #
   466       * ######################
   467       */
   468  
   469      function hashMsg(bytes32 fromPlatform, address fromAccount, bytes32 toPlatform, address toAccount, uint value, string txid) internal pure returns (bytes32) {
   470  
   471          return sha256(bytes32ToStr(fromPlatform), ":0x", uintToStr(uint160(fromAccount), 16), ":", bytes32ToStr(toPlatform), ":0x", uintToStr(uint160(toAccount), 16), ":", uintToStr(value, 10), ":", txid);
   472      }
   473  
   474      function changeVoters(bytes32 platformName, address publicKey, string txid) internal {
   475  
   476          address[] storage voters = platforms[platformName].proposals[txid].voters;
   477  
   478          bool change = true;
   479  
   480          for (uint i = 0; i < voters.length; i++) {
   481  
   482              if (voters[i] == publicKey) {
   483  
   484                  change = false;
   485              }
   486          }
   487  
   488          if (change) {
   489  
   490              voters.push(publicKey);
   491          }
   492      }
   493  
   494      function bytes32ToBytes(bytes32 b) internal pure returns (bytes) {
   495  
   496          uint length = b.length;
   497  
   498          for (uint i = 0; i < b.length; i++) {
   499  
   500              if (b[b.length - 1 - i] == "") {
   501  
   502                  length -= 1;
   503              } else {
   504  
   505                  break;
   506              }
   507          }
   508  
   509          bytes memory bs = new bytes(length);
   510  
   511          for (uint j = 0; j < length; j++) {
   512  
   513              bs[j] = b[j];
   514          }
   515  
   516          return bs;
   517      }
   518  
   519      function bytes32ToStr(bytes32 b) internal pure returns (string) {
   520  
   521          bytes memory bs = bytes32ToBytes(b);
   522  
   523          return string(bs);
   524      }
   525  
   526      function uintToStr(uint value, uint base) internal pure returns (string) {
   527  
   528          uint _value = value;
   529  
   530          uint length = 0;
   531  
   532          bytes16 tenStr = "0123456789abcdef";
   533  
   534          while (true) {
   535  
   536              if (_value > 0) {
   537  
   538                  length ++;
   539  
   540                  _value = _value / base;
   541              } else {
   542  
   543                  break;
   544              }
   545          }
   546  
   547          if (base == 16) {
   548              length = 40;
   549          }
   550  
   551          bytes memory bs = new bytes(length);
   552  
   553          for (uint i = 0; i < length; i++) {
   554  
   555              bs[length - 1 - i] = tenStr[value % base];
   556  
   557              value = value / base;
   558          }
   559  
   560          return string(bs);
   561      }
   562  
   563  }