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 }