github.com/Inphi/go-ethereum@v1.9.7/contracts/checkpointoracle/contract/oracle.sol (about)

     1  pragma solidity ^0.5.10;
     2  
     3  /**
     4   * @title CheckpointOracle
     5   * @author Gary Rong<garyrong@ethereum.org>, Martin Swende <martin.swende@ethereum.org>
     6   * @dev Implementation of the blockchain checkpoint registrar.
     7   */
     8  contract CheckpointOracle {
     9      /*
    10          Events
    11      */
    12  
    13      // NewCheckpointVote is emitted when a new checkpoint proposal receives a vote.
    14      event NewCheckpointVote(uint64 indexed index, bytes32 checkpointHash, uint8 v, bytes32 r, bytes32 s);
    15  
    16      /*
    17          Public Functions
    18      */
    19      constructor(address[] memory _adminlist, uint _sectionSize, uint _processConfirms, uint _threshold) public {
    20          for (uint i = 0; i < _adminlist.length; i++) {
    21              admins[_adminlist[i]] = true;
    22              adminList.push(_adminlist[i]);
    23          }
    24          sectionSize = _sectionSize;
    25          processConfirms = _processConfirms;
    26          threshold = _threshold;
    27      }
    28  
    29      /**
    30       * @dev Get latest stable checkpoint information.
    31       * @return section index
    32       * @return checkpoint hash
    33       * @return block height associated with checkpoint
    34       */
    35      function GetLatestCheckpoint()
    36      view
    37      public
    38      returns(uint64, bytes32, uint) {
    39          return (sectionIndex, hash, height);
    40      }
    41  
    42      // SetCheckpoint sets  a new checkpoint. It accepts a list of signatures
    43      // @_recentNumber: a recent blocknumber, for replay protection
    44      // @_recentHash : the hash of `_recentNumber`
    45      // @_hash : the hash to set at _sectionIndex
    46      // @_sectionIndex : the section index to set
    47      // @v : the list of v-values
    48      // @r : the list or r-values
    49      // @s : the list of s-values
    50      function SetCheckpoint(
    51          uint _recentNumber,
    52          bytes32 _recentHash,
    53          bytes32 _hash,
    54          uint64 _sectionIndex,
    55          uint8[] memory v,
    56          bytes32[] memory r,
    57          bytes32[] memory s)
    58          public
    59          returns (bool)
    60      {
    61          // Ensure the sender is authorized.
    62          require(admins[msg.sender]);
    63  
    64          // These checks replay protection, so it cannot be replayed on forks,
    65          // accidentally or intentionally
    66          require(blockhash(_recentNumber) == _recentHash);
    67  
    68          // Ensure the batch of signatures are valid.
    69          require(v.length == r.length);
    70          require(v.length == s.length);
    71  
    72          // Filter out "future" checkpoint.
    73          if (block.number < (_sectionIndex+1)*sectionSize+processConfirms) {
    74              return false;
    75          }
    76          // Filter out "old" announcement
    77          if (_sectionIndex < sectionIndex) {
    78              return false;
    79          }
    80          // Filter out "stale" announcement
    81          if (_sectionIndex == sectionIndex && (_sectionIndex != 0 || height != 0)) {
    82              return false;
    83          }
    84          // Filter out "invalid" announcement
    85          if (_hash == ""){
    86              return false;
    87          }
    88  
    89          // EIP 191 style signatures
    90          //
    91          // Arguments when calculating hash to validate
    92          // 1: byte(0x19) - the initial 0x19 byte
    93          // 2: byte(0) - the version byte (data with intended validator)
    94          // 3: this - the validator address
    95          // --  Application specific data
    96          // 4 : checkpoint section_index(uint64)
    97          // 5 : checkpoint hash (bytes32)
    98          //     hash = keccak256(checkpoint_index, section_head, cht_root, bloom_root)
    99          bytes32 signedHash = keccak256(abi.encodePacked(byte(0x19), byte(0), this, _sectionIndex, _hash));
   100  
   101          address lastVoter = address(0);
   102  
   103          // In order for us not to have to maintain a mapping of who has already
   104          // voted, and we don't want to count a vote twice, the signatures must
   105          // be submitted in strict ordering.
   106          for (uint idx = 0; idx < v.length; idx++){
   107              address signer = ecrecover(signedHash, v[idx], r[idx], s[idx]);
   108              require(admins[signer]);
   109              require(uint256(signer) > uint256(lastVoter));
   110              lastVoter = signer;
   111              emit NewCheckpointVote(_sectionIndex, _hash, v[idx], r[idx], s[idx]);
   112  
   113              // Sufficient signatures present, update latest checkpoint.
   114              if (idx+1 >= threshold){
   115                  hash = _hash;
   116                  height = block.number;
   117                  sectionIndex = _sectionIndex;
   118                  return true;
   119              }
   120          }
   121          // We shouldn't wind up here, reverting un-emits the events
   122          revert();
   123      }
   124  
   125      /**
   126       * @dev Get all admin addresses
   127       * @return address list
   128       */
   129      function GetAllAdmin()
   130      public
   131      view
   132      returns(address[] memory)
   133      {
   134          address[] memory ret = new address[](adminList.length);
   135          for (uint i = 0; i < adminList.length; i++) {
   136              ret[i] = adminList[i];
   137          }
   138          return ret;
   139      }
   140  
   141      /*
   142          Fields
   143      */
   144      // A map of admin users who have the permission to update CHT and bloom Trie root
   145      mapping(address => bool) admins;
   146  
   147      // A list of admin users so that we can obtain all admin users.
   148      address[] adminList;
   149  
   150      // Latest stored section id
   151      uint64 sectionIndex;
   152  
   153      // The block height associated with latest registered checkpoint.
   154      uint height;
   155  
   156      // The hash of latest registered checkpoint.
   157      bytes32 hash;
   158  
   159      // The frequency for creating a checkpoint
   160      //
   161      // The default value should be the same as the checkpoint size(32768) in the ethereum.
   162      uint sectionSize;
   163  
   164      // The number of confirmations needed before a checkpoint can be registered.
   165      // We have to make sure the checkpoint registered will not be invalid due to
   166      // chain reorg.
   167      //
   168      // The default value should be the same as the checkpoint process confirmations(256)
   169      // in the ethereum.
   170      uint processConfirms;
   171  
   172      // The required signatures to finalize a stable checkpoint.
   173      uint threshold;
   174  }