github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/contracts/chief/src/chief_1.0.0.sol (about) 1 pragma solidity >=0.5.0 <=0.5.3; 2 3 /* for remix 4 import "github.com/SmartMeshFoundation/Spectrum/contracts/chief/src/chief_abs_s0.5.sol"; // for remix 5 import "github.com/SmartMeshFoundation/Spectrum/contracts/chief/src/chief_base_s0.5_v0.0.1.sol"; // for remix 6 */ 7 8 9 /* local */ 10 import "./chief_abs_s0.5.sol"; 11 import "./chief_base_s0.5_v0.0.1.sol"; 12 13 /* 14 ---------- 15 | devnet | 16 ---------- 17 18 test nodes : 19 20 leader : 21 22 privatekey: 507fd083b5c5af7e645e77a3a3a82708f3af304164e02612ab4b1d5b36c627c6 23 address: 0x9944d0cc757cd9391ee320fc17d5b6f61693f2c5 24 25 deposit : 26 27 privatekey: 543e9d0ddcd02b4bbdb2cecd402da99e9532fface57d8ea74e833c5d413f2daa 28 address: 0xd3F50Dfd2887B3818aB9E6c6f846ED1d3bD90B29 29 30 privatekey: 9d7b3b8155ea429cb49cdc556aa7b3367feb91ccf51eb1e9c7e2bac67d939f03 31 address: 0x50bf23F1d844465AB69357aa08Af0fEA4B1E62D7 32 33 34 35 f = "0xbf1736a65f8beadd71b321be585fd883503fdeaa"; personal.unlockAccount(f,"123456") 36 37 sign(f): 38 39 addr: 0xd3F50Dfd2887B3818aB9E6c6f846ED1d3bD90B29 40 R: 0x99b087c99fceee44b15373847e38f485b31b5b779ce7b01081f2d61c00c77d19 41 S: 0x0f29d84ff759415e969e12a49cf2fc453c1b2aa386d59e0488b11627dcdbd261 42 V: 27 43 44 addr: 0x50bf23F1d844465AB69357aa08Af0fEA4B1E62D7 45 R: 0x2edbf406a13757485096ae35d85f1f881f17073e230454ad83a65e003ff2deb8 46 S: 0x4629840c12909009ad4092f8da67d53b57a7a2c8fa6abe024166982d65821fcb 47 V: 27 48 49 50 ChiefBase : 0xad61f1201f592fbf13d2645f9c59d8d5f82a1837 // 51 deploy args : 25,5 52 appendLeader args : "0x9944d0cc757cd9391ee320fc17d5b6f61693f2c5" 53 54 POC : 0x901c0636c4fc83f353bca2db85e2ace886a9416d 55 deploy args : "0xad61f1201f592fbf13d2645f9c59d8d5f82a1837",10,10,50 56 deposit args : 57 "0x99b087c99fceee44b15373847e38f485b31b5b779ce7b01081f2d61c00c77d19","0x0f29d84ff759415e969e12a49cf2fc453c1b2aa386d59e0488b11627dcdbd261",27 58 "0x2edbf406a13757485096ae35d85f1f881f17073e230454ad83a65e003ff2deb8","0x4629840c12909009ad4092f8da67d53b57a7a2c8fa6abe024166982d65821fcb",27 59 60 61 Tribe : 0x6d05f6aa4e19e20cd781fa3def97bbfd0b980534 62 deploy args : "0xad61f1201f592fbf13d2645f9c59d8d5f82a1837","0x901c0636c4fc83f353bca2db85e2ace886a9416d" 63 64 */ 65 66 contract TribeChief_1_0_0 is Chief { 67 68 string vsn = "1.0.0"; 69 70 struct BlackMember { 71 address addr; 72 uint score; 73 uint number; 74 } 75 76 ChiefBase_1_0_0 private base; 77 78 79 address[] public _signerList; //当前轮的17块的出块人列表(包含Leader) 80 address[] public _nextRoundSignerList; //下一轮17块出块人列表,不包含Leader 81 uint public blockNumber; //当前块 82 83 84 85 // the mapping of the signer score and the block number 86 mapping(address => uint) signersMap; //标记某个地址在当前轮中是否是signer 87 88 constructor(address baseAddress, address pocAddress,uint startBlockNumber) public { 89 base = ChiefBase_1_0_0(baseAddress); 90 base.init(pocAddress, address(this)); 91 blockNumber=startBlockNumber; //从此块开始分叉 92 93 address[] memory leaderList = base.takeLeaderList(); 94 require(leaderList.length > 0); 95 96 signersMap[leaderList[0]] = 1; 97 _signerList.push(leaderList[0]); 98 99 for (uint i = _signerList.length; i < base.takeSignerLimit(); i++) { 100 // placeholder 101 _signerList.push(address(0)); 102 } 103 104 } 105 106 modifier allow() { 107 address _addr = msg.sender; 108 require(uint160(_addr) != uint160(0)); 109 require(signersMap[_addr] > 0 || base.isLeader(_addr)); 110 _; 111 } 112 113 function pushNextRoundSigner(address addr) private { 114 if (_nextRoundSignerList.length < base.takeVolunteerLimit()) { 115 _nextRoundSignerList.push(addr); 116 } else{ 117 // revert("next round signer too much"); 118 } 119 } 120 121 // append a signer 122 function pushSigner(address signer ) private { 123 if (_signerList.length < base.takeSignerLimit()) { 124 _signerList.push(signer); 125 signersMap[signer] = 1; 126 } else{ 127 // revert("too many signer"); 128 } 129 } 130 131 // clean all of list and return _signerList[0] 132 function clean_all_signer_and_get0() private returns (address) { 133 address signer0=_signerList[0]; //至少会有一个signer 134 // clean all of signerList 135 for (uint i = 0;i<_signerList.length;i++) { 136 signersMap[_signerList[i]]=0; 137 _signerList[i]=address(0); 138 } 139 _signerList.length=0; 140 return signer0; 141 } 142 143 function genSigners_set_leader(address signer0 ) private { 144 address[] memory leaders = base.takeLeaderList(); 145 for (uint i = 0; i < leaders.length; i++) { 146 address l = leaders[i]; 147 if (signer0 == l) { 148 if (i == leaders.length - 1) { 149 pushSigner(leaders[0]); 150 } else { 151 pushSigner(leaders[i + 1]); 152 } 153 return; 154 } 155 } 156 // revert("signer0 must exist in leader list"); 157 /* 158 there must at least one leader. 159 current leader maybe removed. 160 */ 161 pushSigner(leaders[0]); 162 } 163 164 // push volunteerList to signerList 165 function genSigners_v2s() private { 166 for (uint i = 0; i < _nextRoundSignerList.length; i++) { 167 address v = _nextRoundSignerList[i]; 168 pushSigner(v); 169 } 170 for (uint i = _signerList.length; i < base.takeSignerLimit(); i++) { 171 // placeholder 172 _signerList.push(address(0)); 173 } 174 } 175 176 // clean volunteerList 177 function genSigners_clean_next_round_signers() private { 178 for (uint i =0; i< _nextRoundSignerList.length; i++) { 179 _nextRoundSignerList[i]=address(0); 180 } 181 _nextRoundSignerList.length=0; 182 } 183 184 function genSigners_clean_blackList() private { 185 base.pocCleanBlackList(); 186 } 187 188 function genSigners() private { 189 address signer0=clean_all_signer_and_get0(); 190 require(signer0!=address(0),"signer0 must not be zero"); 191 // generate 192 genSigners_set_leader(signer0); 193 // move next round candidate signers to current signer list 194 genSigners_v2s(); 195 // clear next round candidate signers. 196 genSigners_clean_next_round_signers(); 197 } 198 //合约外部调用唯一的入口 199 function update(address volunteer) public allow() { 200 201 blockNumber = block.number; 202 203 uint l = base.takeSignerLimit(); 204 uint signerIdx = uint(blockNumber % l); //轮到signerIdx出块 205 address si = _signerList[signerIdx]; 206 207 //1 : not leader signer, and `sender!=si` move `si` to waitList in POC contract 208 if (signerIdx > uint(0)) { //leader不是选出来的 209 210 if (uint160(volunteer) != uint160(0)) { 211 pushNextRoundSigner(volunteer); 212 } 213 //轮到si出块,si没有,那么会惩罚si 214 if (si != address(0) && msg.sender != si) { 215 // move si to stopList in POC contract 216 if (base.pocAddStop(si) > 0) { 217 // move to blackList 218 base.pocAddBlackList(si); 219 } 220 delete signersMap[si]; 221 // mark 0 222 _signerList[signerIdx] = address(0); 223 } 224 } 225 226 //2 : last block, reset signerList 227 if (signerIdx == (l - 1)) { 228 genSigners(); //一轮结束,选择下一轮出块人 229 } 230 //拉黑持续时间为一个epoch 231 if (block.number%getEpoch()==0){ 232 // clean blackList 233 genSigners_clean_blackList(); 234 } 235 } 236 237 function getStatus() public view returns ( 238 //address[] volunteerList, 239 address[] memory signerList, 240 address[] memory blackList, // vsn 0.0.3 241 uint[] memory scoreList, 242 uint[] memory numberList, 243 uint totalVolunteer, 244 uint number 245 ) { 246 scoreList = new uint[](_signerList.length); 247 numberList = new uint[](_signerList.length); 248 for (uint i = 0; i < _signerList.length; i ++) { 249 scoreList[i] = 0; 250 numberList[i] = signersMap[_signerList[i]]; 251 } 252 // TODO 253 blackList = base.pocGetBlackList(); 254 255 signerList = _signerList; 256 // vsn 0.0.3 257 number = blockNumber; 258 totalVolunteer = _nextRoundSignerList.length; 259 } 260 261 function version() public view returns (string memory) {return vsn;} 262 263 function getSignerLimit() public view returns (uint) {return base.takeSignerLimit();} 264 265 function getEpoch() public view returns (uint) {return base.takeEpoch();} 266 267 function getVolunteerLimit() public view returns (uint) {return base.takeVolunteerLimit();} 268 //为了保持兼容性,所以名字保持不变 269 function getVolunteers() public view returns ( 270 address[] memory volunteerList, 271 uint[] memory weightList, 272 uint length 273 ){ 274 (volunteerList,length)=getNextRoundSignerList(); 275 weightList = new uint[](length); 276 } 277 function getNextRoundSignerList() public view returns ( 278 address[] memory nextRoundSignerList, 279 uint length 280 ) { 281 nextRoundSignerList=_nextRoundSignerList; 282 length=nextRoundSignerList.length; 283 } 284 285 // TODO 286 function filterVolunteer(address[] memory volunteers) public view returns (uint[] memory result) {} 287 // function test_update(address nextsigner) public{ 288 // update(nextsigner); 289 // } 290 // function test_push_signer(uint256 i,address signer) public{ 291 // _signerList[i]=signer; 292 // signersMap[signer] = 1; 293 // } 294 } 295