github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/consensus/tribe/status.go (about) 1 package tribe 2 3 import ( 4 "crypto/ecdsa" 5 "crypto/elliptic" 6 "encoding/json" 7 "errors" 8 "fmt" 9 "math/big" 10 "time" 11 12 "github.com/SmartMeshFoundation/Spectrum/common" 13 "github.com/SmartMeshFoundation/Spectrum/core/types" 14 "github.com/SmartMeshFoundation/Spectrum/crypto" 15 "github.com/SmartMeshFoundation/Spectrum/log" 16 "github.com/SmartMeshFoundation/Spectrum/params" 17 ) 18 19 func NewTribeStatus() *TribeStatus { 20 ts := &TribeStatus{ 21 Signers: make([]*Signer, 0), 22 SignerLevel: LevelNone, 23 } 24 return ts 25 } 26 27 func (self *TribeStatus) SetTribe(tribe *Tribe) { 28 self.tribe = tribe 29 } 30 31 func (self *TribeStatus) getNodekey() *ecdsa.PrivateKey { 32 if self.nodeKey == nil { 33 panic(errors.New("GetNodekey but nodekey not ready")) 34 } 35 return self.nodeKey 36 } 37 38 func (self *TribeStatus) SetNodeKey(nodeKey *ecdsa.PrivateKey) { 39 self.nodeKey = nodeKey 40 } 41 42 func (self *TribeStatus) GetNodeKey() *ecdsa.PrivateKey { 43 return self.nodeKey 44 } 45 46 func (self *TribeStatus) GetMinerAddress() common.Address { 47 if self.nodeKey == nil { 48 panic(errors.New("GetMinerAddress but nodekey not ready")) 49 } 50 pub := self.nodeKey.PublicKey 51 add := crypto.PubkeyToAddress(pub) 52 return add 53 } 54 func (self *TribeStatus) IsLeader(addr common.Address) bool { 55 for _, a := range self.Leaders { 56 if a == addr { 57 return true 58 } 59 } 60 return false 61 } 62 func (self *TribeStatus) GetMinerAddressByChan(rtn chan common.Address) { 63 go func() { 64 for { 65 if self.nodeKey != nil && self.tribe.isInit { 66 break 67 } 68 <-time.After(time.Second) 69 } 70 pub := self.nodeKey.PublicKey 71 rtn <- crypto.PubkeyToAddress(pub) 72 }() 73 } 74 75 //func (self *TribeStatus) GetSignersFromChiefByHash(hash common.Hash, number *big.Int) ([]*Signer, error) { 76 // sc, ok := self.signersCache.Get(hash) 77 // if ok { 78 // return sc.([]*Signer), nil 79 // } 80 // rtn := params.SendToMsgBoxWithHash("GetStatus", hash, number) 81 // r := <-rtn 82 // if !r.Success { 83 // return nil, r.Entity.(error) 84 // } 85 // cs := r.Entity.(params.ChiefStatus) 86 // signers := cs.SignerList 87 // scores := cs.ScoreList 88 // sl := make([]*Signer, 0, len(signers)) 89 // for i, signer := range signers { 90 // score := scores[i] 91 // sl = append(sl, &Signer{signer, score.Int64()}) 92 // } 93 // self.signersCache.Add(hash, sl) 94 // return sl, nil 95 //} 96 97 // 在每次出块prepare的时候去获取一次,同时在同步区块的时候去获取一次,同步区块获取的是最新块的父区块信息,出块时获取的是当前本地最新块的状态信息 98 func (self *TribeStatus) LoadStatusFromChief(hash common.Hash, number *big.Int) error { 99 //log.Info(fmt.Sprintf("LoadSignersFromChief hash=%s,number=%s", hash.String(), number)) 100 cs, err := params.TribeGetStatus(number, hash) 101 if err != nil { 102 log.Warn("TribeGetStatusError", "err", err, "num", number, "hash", hash.Hex()) 103 return err 104 } 105 signers := cs.SignerList 106 scores := cs.ScoreList 107 sl := make([]*Signer, 0, len(signers)) 108 for i, signer := range signers { 109 score := scores[i] 110 sl = append(sl, &Signer{signer, score.Int64()}) 111 } 112 self.LeaderLimit = cs.LeaderLimit 113 self.Leaders = cs.LeaderList 114 if len(self.Leaders) == 0 && params.IsSIP100Block(number) { 115 panic(fmt.Sprintf("LoadSignersFromChief err ,hash=%s,number=%s,cs=%#v", hash.String(), number, cs)) 116 } 117 self.Number = cs.Number.Int64() 118 self.blackList = cs.BlackList 119 self.loadSigners(sl) 120 self.Epoch, self.SignerLimit = cs.Epoch, cs.SignerLimit 121 go self.resetSignersLevel(hash, number) 122 return nil 123 } 124 125 func (self *TribeStatus) resetSignersLevel(hash common.Hash, number *big.Int) { 126 m := self.GetMinerAddress() 127 for _, s := range self.Signers { 128 if s.Address == m { 129 self.SignerLevel = LevelSigner 130 return 131 } 132 } 133 for _, s := range self.blackList { 134 if s == m { 135 self.SignerLevel = LevelSinner 136 return 137 } 138 } 139 140 for _, s := range self.Leaders { 141 if s == m { 142 self.SignerLevel = LevelSigner 143 return 144 } 145 } 146 147 ci := params.GetChiefInfo(number) 148 switch ci.Version { 149 case "0.0.6": 150 // if filterVolunteer return 1 then is volunteer 151 rtn := params.SendToMsgBoxForFilterVolunteer(hash, number, m) 152 r := <-rtn 153 if r.Success { 154 if fr := r.Entity.(*big.Int); fr != nil && fr.Int64() == 0 { 155 self.SignerLevel = LevelVolunteer 156 return 157 } 158 } 159 } 160 // default none 161 self.SignerLevel = LevelNone 162 } 163 164 //每一块都会调用 165 func (self *TribeStatus) loadSigners(sl []*Signer) { 166 self.Signers = append(self.Signers[:0], sl...) 167 } 168 169 //InTurnForCalcDiffcultyChief100 计算规则参考inTurnForCalcChief100 170 func (self *TribeStatus) InTurnForCalcDiffcultyChief100(signer common.Address, parent *types.Header) *big.Int { 171 return self.inTurnForCalcDifficultyChief100(parent.Number.Int64()+1, parent.Hash(), signer) 172 } 173 174 /* 175 inTurnForCalcDifficultyChief100 计算如果当前出块节点是signer的话,它对应的难度是多少. 176 signers:[0,...,16] 0号对应的是常委会节点,1-16对应的是普通出块节点 177 场景1: 178 1. 当前应该出块节点应该是3,如果signer是3,那么难度就是6. 179 2. 如果singers[0]对应的是常委2, 这时候常委2出块,难度是5,常委3出块难度是4,...,常委1出块难度则是1 180 场景2:当前出块节点应该是singers[0],也就是某个常委会节点 181 1. 如果signers[0] 出块,那么难度就是6 182 2. 假设signers[0]是常委2,那么常委3替他出块难度是5,常委4出块就是4,...常委1出块难度则是2 183 184 这里的number参数主要是选定合约版本,而parentHash则是用来选择读取哪个block时候的合约状态 185 */ 186 func (self *TribeStatus) inTurnForCalcDifficultyChief100(number int64, parentHash common.Hash, signer common.Address) *big.Int { 187 188 signers := self.Signers 189 sl := len(signers) 190 191 defer func() { 192 log.Debug(fmt.Sprintf("inTurnForCalcDifficultyChief100 numer=%d,parentHash=%s signer=%s ", number, parentHash.String(), signer.String()), 193 "signers", signers) 194 }() 195 // log.Info(fmt.Sprintf("singers=%v,signer=%s,leaders=%v,number=%d,parentHash=%s", signers, signer.String(), self.Leaders, number, parentHash.String())) 196 if idx, _, err := self.fetchOnSigners(signer, signers); err == nil { 197 // main 198 if sl > 0 && number%int64(sl) == idx.Int64() { 199 return big.NewInt(diff) 200 } 201 // second 202 if idx.Int64() == 0 { 203 return big.NewInt(diff - 1) 204 } 205 206 } else if sl > 0 { 207 if leaders, err := leaderSort(signers[0].Address, self.Leaders); err == nil { 208 for i, leader := range leaders { 209 if signer == leader && number%int64(sl) == 0 { 210 return big.NewInt(diff - int64(i+1)) 211 } else if signer == leader { 212 return big.NewInt(diff - int64(i+2)) 213 } 214 } 215 } 216 } 217 return diffNoTurn 218 } 219 220 //InTurnForVerifyDifficultyChief100: 计算规则参考inTurnForCalcChief100 221 func (self *TribeStatus) InTurnForVerifyDifficultyChief100(number int64, parentHash common.Hash, signer common.Address) *big.Int { 222 return self.inTurnForCalcDifficultyChief100(number, parentHash, signer) 223 } 224 225 /* 226 假设list=[1,2,3,4,5] 227 first=3,那么返回[4,5,1,2] 228 如果first=2,返回[3,4,5,1] 229 如果first=5,返回[1,2,3,4] 230 不允许返回错误,是因为考虑到运行过程中leader可能会被删除,从而导致找不到leader 231 */ 232 func leaderSort(first common.Address, list []common.Address) ([]common.Address, error) { 233 for i, o := range list { 234 if first == o { 235 return append(list[i+1:], list[:i]...), nil 236 } 237 } 238 239 return list, nil 240 } 241 242 //InTurnForCalcDifficulty 在0.6版本yiqian 计算难度 243 func (self *TribeStatus) InTurnForCalcDifficulty(signer common.Address, parent *types.Header) *big.Int { 244 number := parent.Number.Int64() + 1 245 signers := self.Signers 246 if idx, _, err := self.fetchOnSigners(signer, signers); err == nil { 247 sl := len(signers) 248 if params.IsSIP002Block(big.NewInt(number)) { 249 if sl > 0 && number%int64(sl) == idx.Int64() { 250 return diffInTurnMain 251 } else if sl > 0 && (number+1)%int64(sl) == idx.Int64() { 252 return diffInTurn 253 } 254 } else { 255 if sl > 0 && number%int64(sl) == idx.Int64() { 256 return diffInTurn 257 } 258 } 259 } 260 261 return diffNoTurn 262 } 263 264 //0.6版本之前校验难度 265 func (self *TribeStatus) InTurnForVerifyDiffculty(number int64, parentHash common.Hash, signer common.Address) *big.Int { 266 if ci := params.GetChiefInfo(big.NewInt(number)); ci != nil { 267 switch ci.Version { 268 case "1.0.0": 269 //TODO max value is a var ??? 270 return self.InTurnForVerifyDifficultyChief100(number, parentHash, signer) 271 } 272 } 273 274 var signers []*Signer 275 if number > 3 { 276 signers = self.Signers 277 } else { 278 return diffInTurn 279 } 280 if idx, _, err := self.fetchOnSigners(signer, signers); err == nil { 281 sl := len(signers) 282 if params.IsSIP002Block(big.NewInt(number)) { 283 if sl > 0 && number%int64(sl) == idx.Int64() { 284 return diffInTurnMain 285 } else if sl > 0 && (number+1)%int64(sl) == idx.Int64() { 286 return diffInTurn 287 } 288 } else { 289 if sl > 0 && number%int64(sl) == idx.Int64() { 290 return diffInTurn 291 } 292 } 293 } 294 return diffNoTurn 295 } 296 297 func (self *TribeStatus) genesisSigner(header *types.Header) (common.Address, error) { 298 extraVanity := extraVanityFn(header.Number) 299 signer := common.Address{} 300 copy(signer[:], header.Extra[extraVanity:]) 301 self.loadSigners([]*Signer{{signer, 3}}) 302 return signer, nil 303 } 304 305 //address对应的signer以及其在signers中的下标 306 func (self *TribeStatus) fetchOnSigners(address common.Address, signers []*Signer) (*big.Int, *Signer, error) { 307 if signers == nil { 308 signers = self.Signers 309 } 310 if l := len(signers); l > 0 { 311 for i := 0; i < l; i++ { 312 if s := signers[i]; s.Address == address { 313 return big.NewInt(int64(i)), s, nil 314 } 315 } 316 } 317 return nil, nil, errors.New("not_found") 318 } 319 320 func verifyVrfNum(parent, header *types.Header) (err error) { 321 var ( 322 np = header.Extra[:extraVanityFn(header.Number)] 323 sig = header.Extra[len(header.Extra)-extraSeal:] 324 msg = append(parent.Number.Bytes(), parent.Extra[:32]...) 325 ) 326 pubbuf, err := ecrecoverPubkey(header, sig) 327 if err != nil { 328 //panic(err) //这地方不能panic,否则一个节点出一个恶意的块,所以的节点就全崩了. 329 return err 330 } 331 x, y := elliptic.Unmarshal(crypto.S256(), pubbuf) 332 pubkey := ecdsa.PublicKey{Curve: crypto.S256(), X: x, Y: y} 333 err = crypto.SimpleVRFVerify(&pubkey, msg, np) 334 log.Debug("[verifyVrfNum]", "err", err, "num", header.Number, "vrfn", new(big.Int).SetBytes(np[:32]), "parent", header.ParentHash.Bytes()) 335 return 336 } 337 338 /* 339 validateSigner: 340 1. 验证出块时间符合规则,具体规则见GetPeriodChief100描述 341 2. 342 */ 343 func (self *TribeStatus) validateSigner(parentHeader, header *types.Header, signer common.Address) bool { 344 var ( 345 err error 346 signers = self.Signers 347 number = header.Number.Int64() 348 ) 349 //if number > 1 && self.Number != parentNumber { 350 if number <= CHIEF_NUMBER { 351 return true 352 } 353 354 if params.IsSIP002Block(header.Number) { 355 // second time of verification block time 356 period := self.tribe.GetPeriod(header, signers) 357 pt := parentHeader.Time.Uint64() 358 if pt+period > header.Time.Uint64() { 359 log.Error("[ValidateSigner] second time verification block time error", "num", header.Number, "pt", pt, "period", period, ", pt+period=", pt+period, " , ht=", header.Time.Uint64()) 360 log.Error("[ValidateSigner] second time verification block time error", "err", ErrInvalidTimestampSIP002) 361 return false 362 } 363 } 364 365 if params.IsSIP100Block(header.Number) && header.Coinbase == common.HexToAddress("0x") { 366 log.Error("error_signer", "num", header.Number.String(), "miner", header.Coinbase.Hex(), "signer", signer.Hex()) 367 return false 368 } 369 370 idx, _, err := self.fetchOnSigners(signer, signers) 371 if params.IsSIP100Block(header.Number) { 372 if err == nil { 373 // 轮到谁出就谁出的块 374 idx_m := number % int64(len(signers)) 375 if idx_m == idx.Int64() { 376 return true 377 } 378 // 其他只能有常委会节点替代 379 if idx.Int64() == 0 { 380 return true 381 } 382 } else { 383 // other leader 384 for _, leader := range self.Leaders { 385 if signer == leader { //有没有测试过多个常委会节点同时出块的情况呢? 386 return true 387 } 388 } 389 } 390 } else if err == nil { 391 return true 392 } 393 return false 394 } 395 396 /* 397 VerifySignerBalance: 在chief1.0之前直接通过账号余额来判断是否具有出块资格,chief1.0之后只能通过抵押到poc合约中才具有资格. 398 */ 399 //func (self *TribeStatus) VerifySignerBalance(state *state.StateDB, addr common.Address, header *types.Header) error { 400 // // SIP100 skip this verify 401 // if params.IsSIP100Block(header.Number) { 402 // return nil 403 // } 404 // var ( 405 // pnum, num *big.Int 406 // ) 407 // if addr == common.HexToAddress("0x") { 408 // if _addr, err := ecrecover(header, self.tribe); err == nil { 409 // addr = _addr 410 // } else { 411 // return err 412 // } 413 // } 414 // if header != nil { 415 // num = header.Number 416 // pnum = new(big.Int).Sub(num, big.NewInt(1)) 417 // } else { 418 // return errors.New("params of header can not be null") 419 // } 420 // // skip when v in meshbox.sol 421 // if params.IsReadyMeshbox(pnum) && params.MeshboxExistAddress(addr) { 422 // return nil 423 // } 424 // 425 // return nil 426 // 427 //} 428 429 // every block 430 // sync download or mine 431 // check chief tx 432 func (self *TribeStatus) ValidateBlock(parent, block *types.Block, validateSigner bool) error { 433 if block.Number().Int64() <= CHIEF_NUMBER { 434 return nil 435 } 436 var err error 437 if validateSigner { 438 //The miner updates the chife contract information when prepare, and the follower updates the chief contract information whenValidateBlock. 439 err = self.LoadStatusFromChief(parent.Hash(), block.Number()) 440 if err != nil { 441 log.Error(fmt.Sprintf("[ValidateBlock] LoadSignersFromChief ,parent=%s,current=%s,currentNumber=%s", parent.Hash().String(), block.Hash().String(), block.Number())) 442 return err 443 } 444 } 445 446 header := block.Header() 447 number := header.Number.Int64() 448 449 //number := block.Number().Int64() 450 // add by liangc : seal call this func must skip validate signer 因为这时候签名都还没准备好 451 if validateSigner { 452 signer, err := ecrecover(header, self.tribe) 453 // verify signer 454 if err != nil { 455 return err 456 } 457 // verify difficulty 就算是 458 if !params.IsBeforeChief100block(header.Number) { 459 difficulty := self.InTurnForVerifyDiffculty(number, header.ParentHash, signer) 460 if difficulty.Cmp(header.Difficulty) != 0 { 461 log.Error("** ValidateBlock ERROR **", "head.diff", header.Difficulty.String(), "target.diff", difficulty.String(), "err", errInvalidDifficulty, "validateFromSeal", !validateSigner) 462 return errInvalidDifficulty 463 } 464 } 465 // verify vrf num 466 if params.IsSIP100Block(header.Number) { 467 err = verifyVrfNum(parent.Header(), header) 468 if err != nil { 469 log.Error("vrf_num_fail", "num", number, "err", err) 470 return err 471 } 472 } 473 if !self.validateSigner(parent.Header(), header, signer) { 474 return errUnauthorized 475 } 476 } 477 // check first tx , must be chief.tx , and onely one chief.tx in tx list 478 if block != nil && block.Transactions().Len() == 0 { 479 return ErrTribeNotAllowEmptyTxList 480 } 481 482 var total = 0 483 for i, tx := range block.Transactions() { 484 from := types.GetFromByTx(tx) 485 /* 486 must verify tx.from ==signer: 487 otherwise: 488 if miner A minging the block#16,then A can make chief.update tx fail, 489 so signerList will never update, A will make sure he can mine block for every round. 490 */ 491 if tx.To() != nil && params.IsChiefAddressOnBlock(block.Number(), *tx.To()) && params.IsChiefUpdate(tx.Data()) { 492 if i != 0 { 493 return ErrTribeChiefTxMustAtPositionZero 494 } 495 if validateSigner { 496 signer, err := ecrecover(header, self.tribe) 497 // verify signer 498 if err != nil { 499 return err 500 } 501 502 if from == nil || *from != signer { 503 return ErrTribeChiefTxSignerAndBlockSignerNotMatch 504 } 505 506 if params.IsSIP100Block(header.Number) { 507 // TODO SIP100 check volunteer by vrfnp 508 volunteerHex := common.Bytes2Hex(tx.Data()[4:]) 509 volunteer := common.HexToAddress(volunteerHex) 510 vrfn := header.Extra[:32] 511 if !params.VerifyMiner(header.ParentHash, volunteer, vrfn) { 512 return errors.New("verify_volunteer_fail") 513 } 514 } 515 } 516 total++ 517 } 518 } 519 if total == 0 { 520 return ErrTribeMustContainChiefTx 521 } 522 523 log.Debug("ValidateBlockp-->", "num", block.NumberU64(), "check_signer", validateSigner) 524 return nil 525 } 526 527 func (self *TribeStatus) String() string { 528 if b, e := json.Marshal(self); e != nil { 529 return "error: " + e.Error() 530 } else { 531 return "status: " + string(b) 532 } 533 }