github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/contracts/chief/src/chief_0.0.3.sol (about) 1 // Copyright 2018 The Smartmesh Chain Authors 2 // This file is part of the Spectrum library. 3 pragma solidity ^0.4.19; 4 5 /* 6 vsn 0.0.3 改进如下 : 7 每个 epoch 增加了一个 黑名单,用来保存被淘汰的 signers ,以保证其不会重复被选拔; 8 在每个 epoch 中按打包交易数量来清除 1/3 非 genesisSigners 的节点 ; 9 */ 10 contract TribeChief_0_0_3 { 11 12 // in vsn 0.0.3 , A blacklist is used to save a zero score signature node 13 string vsn = "0.0.3"; 14 15 //config >>>> 16 uint epoch = 11520; // 48H 17 mapping(address => bool) genesisSigner; // genesis signer address 18 uint singerLimit = 5; 19 uint volunteerLimit = 15; 20 //config <<<< 21 22 uint blockNumber; 23 24 //signer info 25 struct SignerInfo { 26 uint score; 27 uint number; 28 } 29 30 address _owner; 31 32 address[] _signerList; 33 address[] _volunteerList; 34 address[] _blackList; 35 36 // the mapping of the signer score and the block number 37 mapping(address => SignerInfo) signersMap; 38 // the mapping of the volunteer and block number 39 mapping(address => uint) volunteersMap; 40 // the mapping of the blacklist and block number 41 mapping(address => uint) blMap; 42 43 // delete a blacklist by index 44 function deleteBlackList(uint index) private { 45 46 uint blen = _blackList.length; 47 if (index < blen) { 48 delete blMap[_blackList[index]]; 49 for (uint i = index; i < blen - 1; i++) { 50 _blackList[i] = _blackList[i + 1]; 51 } 52 _blackList.length -= 1; 53 } 54 } 55 56 // delete a volunteer by index 57 function deleteVolunteer(uint index) private { 58 59 uint vlen = _volunteerList.length; 60 // _signerList >>>> 61 if (index < vlen) { 62 delete volunteersMap[_volunteerList[index]]; 63 for (uint i = index; i < vlen - 1; i++) { 64 _volunteerList[i] = _volunteerList[i + 1]; 65 } 66 _volunteerList.length -= 1; 67 } 68 } 69 70 // delete a signer by index 71 function deleteSigner(uint index) private { 72 uint slen = _signerList.length; 73 if (index < slen) { 74 delete signersMap[_signerList[index]]; 75 for (uint i = index; i < slen - 1; i++) { 76 _signerList[i] = _signerList[i + 1]; 77 } 78 _signerList.length -= 1; 79 } 80 } 81 82 // append a sinner to blacklist 83 function pushBlackList(address sinner) private { 84 85 if (blMap[sinner] == 0) { 86 _blackList.push(sinner); 87 blMap[sinner] = block.number; 88 } 89 } 90 91 // append a volunteer 92 function pushVolunteer(address volunteer) private { 93 //满员或者已经存在于签名人or候选人则不添加 94 //vsn-0.0.3 : blMap is blacklist map , the new volunteer can not in blacklist 95 if (_volunteerList.length < volunteerLimit && volunteersMap[volunteer] == 0 && blMap[volunteer] == 0 && signersMap[volunteer].number == 0) { 96 _volunteerList.push(volunteer); 97 volunteersMap[volunteer] = block.number; 98 } 99 } 100 101 // generate a random index for remove signers every epoch 102 function getRandomIdx(address addr, uint max) private returns (uint256) { 103 uint256 random = uint256(keccak256(addr, block.difficulty, now)); 104 return (random % max); 105 } 106 107 // append a signer 108 function pushSigner(address signer, uint score) private { 109 110 if (_signerList.length < singerLimit) { 111 _signerList.push(signer); 112 signersMap[signer].score = score; 113 signersMap[signer].number = block.number; 114 } 115 } 116 117 function TribeChief_0_0_3(address[] genesisSigners) public { 118 _owner = msg.sender; 119 uint len = genesisSigners.length; 120 if (len > 0) { 121 for (uint i = 0; i < len; i++) { 122 address g = genesisSigners[i]; 123 genesisSigner[g] = true; 124 pushSigner(g, 3); 125 } 126 } else { 127 // normal default for testing 128 address g1 = 0x4110bd1ff0b73fa12c259acf39c950277f266787; 129 // nerver delete genesis signer 130 genesisSigner[g1] = true; 131 pushSigner(g1, 3); 132 } 133 } 134 135 modifier apply(address _addr) { 136 require(signersMap[_addr].number > 0); 137 _; 138 } 139 modifier owner(address _addr) { 140 require(_addr == _owner); 141 _; 142 } 143 144 function setVolunteerLimit(uint n) public apply(msg.sender) { 145 volunteerLimit = n; 146 } 147 148 function setSingerLimit(uint n) public apply(msg.sender) { 149 singerLimit = n; 150 } 151 152 function repeatTi(uint[] tiList, uint ti) private returns (bool) { 153 if (tiList.length > 0) { 154 for (uint i = 0; i < tiList.length; i++) { 155 if (tiList[i] == ti) { 156 return true; 157 } 158 } 159 } 160 return false; 161 } 162 163 function update(address volunteer) public apply(msg.sender) { 164 165 blockNumber = block.number; 166 167 // vsn-0.0.2 : every epoch be clean volunteers 168 // vsn-0.0.3 : clean blacklist and move 1/3 signers to blacklist excelude genesisSigners 169 if (block.number > epoch && block.number % epoch == 0) { 170 171 // ==== vsn-0.0.2 ==== 172 uint vlen = _volunteerList.length; 173 for (uint i1 = 0; i1 < vlen; i1++) { 174 delete volunteersMap[_volunteerList[i1]]; 175 } 176 delete _volunteerList; 177 178 // ==== vsn-0.0.3 ==== 179 // 1 : clean blacklist 180 uint blen = _blackList.length; 181 for (uint i2 = 0; i2 < blen; i2++) { 182 delete blMap[_blackList[i2]]; 183 } 184 delete _blackList; 185 // 2 : move 1/3 signers to blacklist 186 uint slen = _signerList.length; 187 uint counter = 0; 188 uint[] memory tiList; 189 // target signer idx 190 for (uint i3 = (slen - 1); i3 >= 0; i3--) { 191 address _addr = _signerList[i3]; 192 uint ti = getRandomIdx(_addr, (slen - 1)); 193 //skip genesis signer 194 if (genesisSigner[_signerList[ti]]) { 195 continue; 196 } 197 if (repeatTi(tiList, ti)) { 198 continue; 199 } 200 tiList[counter] = ti; 201 if (counter++ >= (slen / 3)) break; 202 } 203 if (tiList.length > 0) { 204 for (uint i4 = 0; i4 < tiList.length; i4++) { 205 pushBlackList(_signerList[tiList[i4]]); 206 deleteSigner(tiList[i4]); 207 } 208 } 209 } 210 211 // mine 212 // 如果当前块 不是 signers[ blockNumber % signers.length ] 出的,就给这个 signer 减分 213 // 否则恢复成 3 分 214 uint signerIdx = blockNumber % _signerList.length; 215 //初始签名人不做处理 216 if (!genesisSigner[_signerList[signerIdx]]) { 217 218 SignerInfo storage signer = signersMap[_signerList[signerIdx]]; 219 220 // 序号对应的不是我,则扣它一分 221 if (msg.sender != _signerList[signerIdx]) { 222 if (signer.score > 1) { 223 signer.score -= 1; 224 signer.number = blockNumber; 225 } else { 226 // move to blacklist and cannot be selected in this epoch 227 pushBlackList(_signerList[signerIdx]); 228 // vsn-0.0.3 229 // score == 0 , remove on signerList 230 deleteSigner(signerIdx); 231 } 232 } else { 233 // 恢复分数 234 signer.score = 3; 235 } 236 } 237 238 // tag 239 if (volunteer != uint160(0)) { 240 pushVolunteer(volunteer); 241 } 242 243 //是否提拔一个人到签名人 244 if (_signerList.length < singerLimit && _volunteerList.length > 0) { 245 246 //将候选人列表首个添加到签名人列表 247 pushSigner(_volunteerList[0], 3); 248 249 //删除该候补志愿者 250 deleteVolunteer(0); 251 } 252 } 253 254 function version() constant returns (string) { 255 return vsn; 256 } 257 258 function getSignerLimit() constant returns (uint) { 259 return singerLimit; 260 } 261 262 function getVolunteerLimit() constant returns (uint) { 263 return volunteerLimit; 264 } 265 266 function getStatus() constant returns ( 267 address[] volunteerList, 268 address[] signerList, 269 address[] blackList, // vsn 0.0.3 270 uint[] memory scoreList, 271 uint[] memory numberList, 272 uint number 273 ) { 274 scoreList = new uint[](_signerList.length); 275 numberList = new uint[](_signerList.length); 276 for (uint i = 0; i < _signerList.length; i ++) { 277 scoreList[i] = signersMap[_signerList[i]].score; 278 numberList[i] = signersMap[_signerList[i]].number; 279 } 280 volunteerList = _volunteerList; 281 signerList = _signerList; 282 blackList = _blackList; 283 // vsn 0.0.3 284 number = blockNumber; 285 return; 286 } 287 288 }