github.com/Gessiux/neatchain@v1.3.1/chain/consensus/neatcon/epoch/epoch.go (about) 1 package epoch 2 3 import ( 4 "errors" 5 "fmt" 6 7 goCrypto "github.com/Gessiux/go-crypto" 8 dbm "github.com/Gessiux/go-db" 9 "github.com/Gessiux/go-wire" 10 tmTypes "github.com/Gessiux/neatchain/chain/consensus/neatcon/types" 11 "github.com/Gessiux/neatchain/chain/core/state" 12 "github.com/Gessiux/neatchain/chain/core/types" 13 "github.com/Gessiux/neatchain/chain/log" 14 "github.com/Gessiux/neatchain/utilities/common" 15 16 //"math" 17 "math/big" 18 "sort" 19 "strconv" 20 "sync" 21 "time" 22 ) 23 24 var NextEpochNotExist = errors.New("next epoch parameters do not exist, fatal error") 25 var NextEpochNotEXPECTED = errors.New("next epoch parameters are not excepted, fatal error") 26 27 var ForbiddenEpoch = big.NewInt(2) // forbid 2 epoch 28 29 const ( 30 EPOCH_NOT_EXIST = iota // value --> 0 31 EPOCH_PROPOSED_NOT_VOTED // value --> 1 32 EPOCH_VOTED_NOT_SAVED // value --> 2 33 EPOCH_SAVED // value --> 3 34 35 MinimumValidatorsSize = 1 36 MaximumValidatorsSize = 100 // TODO the max validator size will increase to 100 in the future 37 38 epochKey = "Epoch:%v" 39 latestEpochKey = "LatestEpoch" 40 41 TimeForForbidden = 4 * time.Hour 42 ForbiddenDuration = 24 * time.Hour 43 ) 44 45 type Epoch struct { 46 mtx sync.Mutex 47 db dbm.DB 48 49 Number uint64 50 RewardPerBlock *big.Int 51 StartBlock uint64 52 EndBlock uint64 53 StartTime time.Time 54 EndTime time.Time //not accurate for current epoch 55 BlockGenerated int //agreed in which block 56 Status int //checked if this epoch has been saved 57 Validators *tmTypes.ValidatorSet 58 59 // The VoteSet will be used just before Epoch Start 60 validatorVoteSet *EpochValidatorVoteSet // VoteSet store with key prefix EpochValidatorVote_ 61 rs *RewardScheme // RewardScheme store with key REWARDSCHEME 62 previousEpoch *Epoch 63 nextEpoch *Epoch 64 65 logger log.Logger 66 } 67 68 func calcEpochKeyWithHeight(number uint64) []byte { 69 return []byte(fmt.Sprintf(epochKey, number)) 70 } 71 72 // InitEpoch either initial the Epoch from DB or from genesis file 73 func InitEpoch(db dbm.DB, genDoc *tmTypes.GenesisDoc, logger log.Logger) *Epoch { 74 75 epochNumber := db.Get([]byte(latestEpochKey)) 76 if epochNumber == nil { 77 // Read Epoch from Genesis 78 rewardScheme := MakeRewardScheme(db, &genDoc.RewardScheme) 79 rewardScheme.Save() 80 81 ep := MakeOneEpoch(db, &genDoc.CurrentEpoch, logger) 82 ep.Save() 83 84 ep.SetRewardScheme(rewardScheme) 85 return ep 86 } else { 87 // Load Epoch from DB 88 epNo, _ := strconv.ParseUint(string(epochNumber), 10, 64) 89 return LoadOneEpoch(db, epNo, logger) 90 } 91 } 92 93 // Load Full Epoch By EpochNumber (Epoch data, Reward Scheme, ValidatorVote, Previous Epoch, Next Epoch) 94 func LoadOneEpoch(db dbm.DB, epochNumber uint64, logger log.Logger) *Epoch { 95 // Load Epoch Data from DB 96 epoch := loadOneEpoch(db, epochNumber, logger) 97 // Set Reward Scheme 98 rewardscheme := LoadRewardScheme(db) 99 epoch.rs = rewardscheme 100 // Set Validator VoteSet if has 101 epoch.validatorVoteSet = LoadEpochVoteSet(db, epochNumber) 102 // Set Previous Epoch 103 if epochNumber > 0 { 104 epoch.previousEpoch = loadOneEpoch(db, epochNumber-1, logger) 105 if epoch.previousEpoch != nil { 106 epoch.previousEpoch.rs = rewardscheme 107 } 108 } 109 // Set Next Epoch 110 epoch.nextEpoch = loadOneEpoch(db, epochNumber+1, logger) 111 if epoch.nextEpoch != nil { 112 epoch.nextEpoch.rs = rewardscheme 113 // Set ValidatorVoteSet 114 epoch.nextEpoch.validatorVoteSet = LoadEpochVoteSet(db, epochNumber+1) 115 } 116 117 return epoch 118 } 119 120 func loadOneEpoch(db dbm.DB, epochNumber uint64, logger log.Logger) *Epoch { 121 122 buf := db.Get(calcEpochKeyWithHeight(epochNumber)) 123 ep := FromBytes(buf) 124 if ep != nil { 125 ep.db = db 126 ep.logger = logger 127 } 128 return ep 129 } 130 131 // Convert from OneEpochDoc (Json) to Epoch 132 func MakeOneEpoch(db dbm.DB, oneEpoch *tmTypes.OneEpochDoc, logger log.Logger) *Epoch { 133 134 //fmt.Printf("MakeOneEpoch onEpoch=%v\n", oneEpoch) 135 //fmt.Printf("MakeOneEpoch validators=%v\n", oneEpoch.Validators) 136 validators := make([]*tmTypes.Validator, len(oneEpoch.Validators)) 137 for i, val := range oneEpoch.Validators { 138 // Make validator 139 validators[i] = &tmTypes.Validator{ 140 Address: val.EthAccount.Bytes(), 141 PubKey: val.PubKey, 142 VotingPower: val.Amount, 143 RemainingEpoch: val.RemainingEpoch, 144 } 145 } 146 147 te := &Epoch{ 148 db: db, 149 150 Number: oneEpoch.Number, 151 RewardPerBlock: oneEpoch.RewardPerBlock, 152 StartBlock: oneEpoch.StartBlock, 153 EndBlock: oneEpoch.EndBlock, 154 StartTime: time.Now(), 155 EndTime: time.Unix(0, 0), //not accurate for current epoch 156 Status: oneEpoch.Status, 157 Validators: tmTypes.NewValidatorSet(validators), 158 159 logger: logger, 160 } 161 162 return te 163 } 164 165 func (epoch *Epoch) GetDB() dbm.DB { 166 return epoch.db 167 } 168 169 func (epoch *Epoch) GetEpochValidatorVoteSet() *EpochValidatorVoteSet { 170 //try reload validatorVoteSet 171 if epoch.validatorVoteSet == nil { 172 epoch.validatorVoteSet = LoadEpochVoteSet(epoch.db, epoch.Number) 173 } 174 return epoch.validatorVoteSet 175 } 176 177 func (epoch *Epoch) GetRewardScheme() *RewardScheme { 178 return epoch.rs 179 } 180 181 func (epoch *Epoch) SetRewardScheme(rs *RewardScheme) { 182 epoch.rs = rs 183 } 184 185 // Save the Epoch to Level DB 186 func (epoch *Epoch) Save() { 187 epoch.mtx.Lock() 188 defer epoch.mtx.Unlock() 189 //fmt.Printf("(epoch *Epoch) Save(), (EPOCH, ts.Bytes()) are: (%s,%v\n", calcEpochKeyWithHeight(epoch.Number), epoch.Bytes()) 190 epoch.db.SetSync(calcEpochKeyWithHeight(epoch.Number), epoch.Bytes()) 191 epoch.db.SetSync([]byte(latestEpochKey), []byte(strconv.FormatUint(epoch.Number, 10))) 192 193 if epoch.nextEpoch != nil && epoch.nextEpoch.Status == EPOCH_VOTED_NOT_SAVED { 194 epoch.nextEpoch.Status = EPOCH_SAVED 195 // Save the next epoch 196 epoch.db.SetSync(calcEpochKeyWithHeight(epoch.nextEpoch.Number), epoch.nextEpoch.Bytes()) 197 } 198 199 // TODO whether save next epoch validator vote set 200 //if epoch.nextEpoch != nil && epoch.nextEpoch.validatorVoteSet != nil { 201 // // Save the next epoch vote set 202 // SaveEpochVoteSet(epoch.db, epoch.nextEpoch.Number, epoch.nextEpoch.validatorVoteSet) 203 //} 204 } 205 206 func FromBytes(buf []byte) *Epoch { 207 208 if len(buf) == 0 { 209 return nil 210 } else { 211 ep := &Epoch{} 212 err := wire.ReadBinaryBytes(buf, ep) 213 if err != nil { 214 log.Errorf("Load Epoch from Bytes Failed, error: %v", err) 215 return nil 216 } 217 return ep 218 } 219 } 220 221 func (epoch *Epoch) Bytes() []byte { 222 return wire.BinaryBytes(*epoch) 223 } 224 225 func (epoch *Epoch) ValidateNextEpoch(next *Epoch, lastHeight uint64, lastBlockTime time.Time) error { 226 227 myNextEpoch := epoch.ProposeNextEpoch(lastHeight, lastBlockTime) 228 229 if !myNextEpoch.Equals(next, false) { 230 log.Warnf("next epoch parameters are not expected, epoch propose next epoch: %v, next %v", myNextEpoch.String(), next.String()) 231 return NextEpochNotEXPECTED 232 } 233 234 return nil 235 } 236 237 //check if need propose next epoch 238 func (epoch *Epoch) ShouldProposeNextEpoch(curBlockHeight uint64) bool { 239 // If next epoch already proposed, then no need propose again 240 //fmt.Printf("should propose next epoch %v\n", epoch.nextEpoch) 241 if epoch.nextEpoch != nil { 242 //fmt.Printf("should propose next epoch") 243 return false 244 } 245 246 // current block height bigger than epoch start block and not equal to 1 247 shouldPropose := curBlockHeight > epoch.StartBlock && curBlockHeight != 1 && curBlockHeight != epoch.EndBlock 248 return shouldPropose 249 } 250 251 func (epoch *Epoch) ProposeNextEpoch(lastBlockHeight uint64, lastBlockTime time.Time) *Epoch { 252 253 if epoch != nil { 254 255 rewardPerBlock, blocks := epoch.estimateForNextEpoch(lastBlockHeight, lastBlockTime) 256 257 next := &Epoch{ 258 mtx: epoch.mtx, 259 db: epoch.db, 260 261 Number: epoch.Number + 1, 262 RewardPerBlock: rewardPerBlock, 263 StartBlock: epoch.EndBlock + 1, 264 EndBlock: epoch.EndBlock + blocks, 265 BlockGenerated: 0, 266 Status: EPOCH_PROPOSED_NOT_VOTED, 267 Validators: epoch.Validators.Copy(), // Old Validators 268 269 logger: epoch.logger, 270 } 271 272 return next 273 } 274 return nil 275 } 276 277 func (epoch *Epoch) GetNextEpoch() *Epoch { 278 if epoch.nextEpoch == nil { 279 epoch.nextEpoch = loadOneEpoch(epoch.db, epoch.Number+1, epoch.logger) 280 if epoch.nextEpoch != nil { 281 epoch.nextEpoch.rs = epoch.rs 282 // Set ValidatorVoteSet 283 epoch.nextEpoch.validatorVoteSet = LoadEpochVoteSet(epoch.db, epoch.Number+1) 284 } 285 } 286 return epoch.nextEpoch 287 } 288 289 func (epoch *Epoch) SetNextEpoch(next *Epoch) { 290 if next != nil { 291 next.db = epoch.db 292 next.rs = epoch.rs 293 next.logger = epoch.logger 294 } 295 epoch.nextEpoch = next 296 } 297 298 func (epoch *Epoch) GetPreviousEpoch() *Epoch { 299 return epoch.previousEpoch 300 } 301 302 func (epoch *Epoch) ShouldEnterNewEpoch(height uint64, state *state.StateDB) (bool, *tmTypes.ValidatorSet, error) { 303 304 if height == epoch.EndBlock { 305 epoch.nextEpoch = epoch.GetNextEpoch() 306 if epoch.nextEpoch != nil { 307 308 // Step 1: Refund the Delegate (subtract the pending refund / deposit proxied amount) 309 for refundAddress := range state.GetDelegateAddressRefundSet() { 310 state.ForEachProxied(refundAddress, func(key common.Address, proxiedBalance, depositProxiedBalance, pendingRefundBalance *big.Int) bool { 311 if pendingRefundBalance.Sign() > 0 { 312 // Refund Pending Refund 313 state.SubDepositProxiedBalanceByUser(refundAddress, key, pendingRefundBalance) 314 state.SubPendingRefundBalanceByUser(refundAddress, key, pendingRefundBalance) 315 state.SubDelegateBalance(key, pendingRefundBalance) 316 state.AddBalance(key, pendingRefundBalance) 317 } 318 return true 319 }) 320 // reset commission = 0 if not candidate 321 if !state.IsCandidate(refundAddress) { 322 state.ClearCommission(refundAddress) 323 } 324 } 325 state.ClearDelegateRefundSet() 326 327 // Step 2: Sort the Validators and potential Validators (with success vote) base on deposit amount + deposit proxied amount 328 // Step 2.1: Update deposit amount base on the vote (Add/Substract deposit amount base on vote) 329 // Step 2.2: Add candidate to next epoch vote set 330 // Step 2.3: Sort the address with deposit + deposit proxied amount 331 var ( 332 refunds []*tmTypes.RefundValidatorAmount 333 ) 334 335 newValidators := epoch.Validators.Copy() 336 // Invoke the get next epoch method to avoid next epoch vote set is nil 337 nextEpochVoteSet := epoch.GetNextEpoch().GetEpochValidatorVoteSet().Copy() // copy vote set 338 candidateList := state.GetCandidateSet() 339 340 for _, v := range newValidators.Validators { 341 vAddr := common.BytesToAddress(v.Address) 342 if !state.GetForbidden(vAddr) { 343 fmt.Printf("Should enter new epoch, validator %v is not forbidden\n", vAddr.String()) 344 totalProxiedBalance := new(big.Int).Add(state.GetTotalProxiedBalance(vAddr), state.GetTotalDepositProxiedBalance(vAddr)) 345 // Voting Power = Proxied amount + Deposit amount 346 newVotingPower := new(big.Int).Add(totalProxiedBalance, state.GetDepositBalance(vAddr)) 347 if newVotingPower.Sign() == 0 { 348 newValidators.Remove(v.Address) 349 } else { 350 v.VotingPower = newVotingPower 351 } 352 } else { 353 // if forbidden then remove from the validator set and candidate list 354 newValidators.Remove(v.Address) 355 delete(candidateList, vAddr) 356 357 // if forbidden epoch bigger than 0, subtract 1 epoch 358 forbiddenEpoch := state.GetForbiddenTime(vAddr) 359 if forbiddenEpoch.Cmp(common.Big0) == 1 { 360 forbiddenEpoch.Sub(forbiddenEpoch, common.Big1) 361 state.SetForbiddenTime(vAddr, forbiddenEpoch) 362 fmt.Printf("Should enter new epoch 1, left forbidden epoch is %v\n", forbiddenEpoch) 363 } 364 365 refunds = append(refunds, &tmTypes.RefundValidatorAmount{Address: vAddr, Amount: v.VotingPower, Voteout: true}) 366 epoch.logger.Debugf("Should enter new epoch, validator %v is forbidden", vAddr.String()) 367 } 368 } 369 370 if nextEpochVoteSet == nil { 371 nextEpochVoteSet = NewEpochValidatorVoteSet() 372 fmt.Printf("Should enter new epoch, next epoch vote set is nil, %v\n", nextEpochVoteSet) 373 } 374 375 // if has candidate and next epoch vote set not nil, add them to next epoch vote set 376 if len(candidateList) > 0 { 377 for addr := range candidateList { 378 if state.GetForbidden(addr) { 379 // first, delete from the candidate list 380 delete(candidateList, addr) 381 382 // if forbidden epoch bigger than 0, subtract 1 epoch 383 forbiddenEpoch := state.GetForbiddenTime(addr) 384 if forbiddenEpoch.Cmp(common.Big0) == 1 { 385 forbiddenEpoch.Sub(forbiddenEpoch, common.Big1) 386 state.SetForbiddenTime(addr, forbiddenEpoch) 387 fmt.Printf("Should enter new epoch 2, left forbidden epoch is %v\n", forbiddenEpoch) 388 } 389 } 390 } 391 392 epoch.logger.Debugf("Add candidate to next epoch vote set before, candidate: %v", candidateList) 393 394 for _, v := range newValidators.Validators { 395 vAddr := common.BytesToAddress(v.Address) 396 delete(candidateList, vAddr) 397 } 398 399 for _, v := range nextEpochVoteSet.Votes { 400 // first, delete from the candidate list 401 delete(candidateList, v.Address) 402 } 403 404 epoch.logger.Debugf("Add candidate to next epoch vote set after, candidate: %v", candidateList) 405 406 var voteArr []*EpochValidatorVote 407 for addr := range candidateList { 408 if state.IsCandidate(addr) { 409 // calculate the net proxied balance of this candidate 410 proxiedBalance := state.GetTotalProxiedBalance(addr) 411 // TODO if need add the deposit proxied balance 412 depositProxiedBalance := state.GetTotalDepositProxiedBalance(addr) 413 // TODO if need subtraction the pending refund balance 414 pendingRefundBalance := state.GetTotalPendingRefundBalance(addr) 415 netProxied := new(big.Int).Sub(new(big.Int).Add(proxiedBalance, depositProxiedBalance), pendingRefundBalance) 416 417 if netProxied.Sign() == -1 { 418 continue 419 } 420 421 // TODO whether need move the delegate amount now 422 // Move delegate amount first if Candidate 423 state.ForEachProxied(addr, func(key common.Address, proxiedBalance, depositProxiedBalance, pendingRefundBalance *big.Int) bool { 424 // Move Proxied Amount to Deposit Proxied Amount 425 state.SubProxiedBalanceByUser(addr, key, proxiedBalance) 426 state.AddDepositProxiedBalanceByUser(addr, key, proxiedBalance) 427 return true 428 }) 429 430 pubkey := state.GetPubkey(addr) 431 pubkeyBytes := common.FromHex(pubkey) 432 if pubkey == "" || len(pubkeyBytes) != 128 { 433 continue 434 } 435 var blsPK goCrypto.BLSPubKey 436 copy(blsPK[:], pubkeyBytes) 437 438 vote := &EpochValidatorVote{ 439 Address: addr, 440 Amount: netProxied, 441 PubKey: blsPK, 442 Salt: "neatchain", 443 TxHash: common.Hash{}, 444 } 445 voteArr = append(voteArr, vote) 446 fmt.Printf("vote %v\n", vote) 447 //nextEpochVoteSet.StoreVote(vote) 448 } 449 } 450 451 // Sort the vote by amount and address 452 sort.Slice(voteArr, func(i, j int) bool { 453 if voteArr[i].Amount.Cmp(voteArr[j].Amount) == 0 { 454 return compareAddress(voteArr[i].Address[:], voteArr[j].Address[:]) 455 } else { 456 return voteArr[i].Amount.Cmp(voteArr[j].Amount) == 1 457 } 458 }) 459 460 // Store the vote 461 for i := range voteArr { 462 fmt.Printf("address:%v, amount: %v\n", voteArr[i].Address.String(), voteArr[i].Amount) 463 nextEpochVoteSet.StoreVote(voteArr[i]) 464 } 465 } 466 467 // Update Validators with vote 468 //refundsUpdate, err := updateEpochValidatorSet(newValidators, epoch.nextEpoch.validatorVoteSet) 469 refundsUpdate, err := updateEpochValidatorSet(newValidators, nextEpochVoteSet) 470 if err != nil { 471 epoch.logger.Warn("Error changing validator set", "error", err) 472 return false, nil, err 473 } 474 refunds = append(refunds, refundsUpdate...) 475 476 // Now newValidators become a real new Validators 477 // Step 3: Special Case: For the existing Validator + Candidate + no vote, Move proxied amount to deposit proxied amount (proxied amount -> deposit proxied amount) 478 for _, v := range newValidators.Validators { 479 vAddr := common.BytesToAddress(v.Address) 480 if state.IsCandidate(vAddr) && state.GetTotalProxiedBalance(vAddr).Sign() > 0 { 481 state.ForEachProxied(vAddr, func(key common.Address, proxiedBalance, depositProxiedBalance, pendingRefundBalance *big.Int) bool { 482 if proxiedBalance.Sign() > 0 { 483 // Deposit the proxied amount 484 state.SubProxiedBalanceByUser(vAddr, key, proxiedBalance) 485 state.AddDepositProxiedBalanceByUser(vAddr, key, proxiedBalance) 486 } 487 return true 488 }) 489 } 490 } 491 492 // Step 4: For vote out Address, refund deposit (deposit amount -> balance, deposit proxied amount -> proxied amount) 493 for _, r := range refunds { 494 if !r.Voteout { 495 // Normal Refund, refund the deposit back to the self balance 496 state.SubDepositBalance(r.Address, r.Amount) 497 state.AddBalance(r.Address, r.Amount) 498 } else { 499 // Voteout Refund, refund the deposit both to self and proxied (if available) 500 if state.IsCandidate(r.Address) { 501 state.ForEachProxied(r.Address, func(key common.Address, proxiedBalance, depositProxiedBalance, pendingRefundBalance *big.Int) bool { 502 if depositProxiedBalance.Sign() > 0 { 503 state.SubDepositProxiedBalanceByUser(r.Address, key, depositProxiedBalance) 504 state.AddProxiedBalanceByUser(r.Address, key, depositProxiedBalance) 505 } 506 return true 507 }) 508 } 509 // Refund all the self deposit balance 510 depositBalance := state.GetDepositBalance(r.Address) 511 state.SubDepositBalance(r.Address, depositBalance) 512 state.AddBalance(r.Address, depositBalance) 513 } 514 } 515 516 return true, newValidators, nil 517 } else { 518 return false, nil, NextEpochNotExist 519 } 520 } 521 return false, nil, nil 522 } 523 524 func compareAddress(addrA, addrB []byte) bool { 525 if addrA[0] == addrB[0] { 526 return compareAddress(addrA[1:], addrB[1:]) 527 } else { 528 return addrA[0] > addrB[0] 529 } 530 } 531 532 // Move to New Epoch 533 func (epoch *Epoch) EnterNewEpoch(newValidators *tmTypes.ValidatorSet) (*Epoch, error) { 534 if epoch.nextEpoch != nil { 535 now := time.Now() 536 537 // Set the End Time for current Epoch and Save it 538 epoch.EndTime = now 539 epoch.Save() 540 // Old Epoch Ended 541 epoch.logger.Infof("Epoch %v reach to his end", epoch.Number) 542 543 // Now move to Next Epoch 544 nextEpoch := epoch.nextEpoch 545 // Store the Previous Epoch Validators only 546 //nextEpoch.previousEpoch = &Epoch{Validators: epoch.Validators} 547 // Store the Previous Epoch all 548 nextEpoch.previousEpoch = epoch.Copy() // if directly use epoch, it will falat error stack overflow (goroutine stack exceeds 1000000000-byte limit) 549 nextEpoch.StartTime = now 550 nextEpoch.Validators = newValidators 551 552 nextEpoch.nextEpoch = nil //suppose we will not generate a more epoch after next-epoch 553 nextEpoch.Save() 554 epoch.logger.Infof("Enter into New Epoch %v", nextEpoch) 555 return nextEpoch, nil 556 } else { 557 return nil, NextEpochNotExist 558 } 559 } 560 561 // DryRunUpdateEpochValidatorSet Re-calculate the New Validator Set base on the current state db and vote set 562 func DryRunUpdateEpochValidatorSet(state *state.StateDB, validators *tmTypes.ValidatorSet, voteSet *EpochValidatorVoteSet) error { 563 564 for _, v := range validators.Validators { 565 vAddr := common.BytesToAddress(v.Address) 566 567 // Deposit Proxied + Proxied - Pending Refund 568 totalProxiedBalance := new(big.Int).Add(state.GetTotalProxiedBalance(vAddr), state.GetTotalDepositProxiedBalance(vAddr)) 569 totalProxiedBalance.Sub(totalProxiedBalance, state.GetTotalPendingRefundBalance(vAddr)) 570 571 // Voting Power = Delegated amount + Deposit amount 572 newVotingPower := new(big.Int).Add(totalProxiedBalance, state.GetDepositBalance(vAddr)) 573 if newVotingPower.Sign() == 0 { 574 validators.Remove(v.Address) 575 } else { 576 v.VotingPower = newVotingPower 577 } 578 } 579 580 _, err := updateEpochValidatorSet(validators, voteSet) 581 return err 582 } 583 584 // updateEpochValidatorSet Update the Current Epoch Validator by vote 585 // 586 func updateEpochValidatorSet(validators *tmTypes.ValidatorSet, voteSet *EpochValidatorVoteSet) ([]*tmTypes.RefundValidatorAmount, error) { 587 588 // Refund List will be vaildators contain from Vote (exit validator or less amount than previous amount) and Knockout after sort by amount 589 var refund []*tmTypes.RefundValidatorAmount 590 oldValSize, newValSize := validators.Size(), 0 591 592 // Process the Vote if vote set not empty 593 if !voteSet.IsEmpty() { 594 // Process the Votes and merge into the Validator Set 595 for _, v := range voteSet.Votes { 596 // If vote not reveal, bypass this vote 597 if v.Amount == nil || v.Salt == "" || v.PubKey == nil { 598 continue 599 } 600 601 _, validator := validators.GetByAddress(v.Address[:]) 602 if validator == nil { 603 // Add the new validator 604 added := validators.Add(tmTypes.NewValidator(v.Address[:], v.PubKey, v.Amount)) 605 if !added { 606 return nil, fmt.Errorf("Failed to add new validator %v with voting power %d", v.Address, v.Amount) 607 } 608 newValSize++ 609 } else if v.Amount.Sign() == 0 { 610 refund = append(refund, &tmTypes.RefundValidatorAmount{Address: v.Address, Amount: validator.VotingPower, Voteout: false}) 611 // Remove the Validator 612 _, removed := validators.Remove(validator.Address) 613 if !removed { 614 return nil, fmt.Errorf("Failed to remove validator %v", validator.Address) 615 } 616 } else { 617 //refund if new amount less than the voting power 618 if v.Amount.Cmp(validator.VotingPower) == -1 { 619 refundAmount := new(big.Int).Sub(validator.VotingPower, v.Amount) 620 refund = append(refund, &tmTypes.RefundValidatorAmount{Address: v.Address, Amount: refundAmount, Voteout: false}) 621 } 622 623 // Update the Validator Amount 624 validator.VotingPower = v.Amount 625 updated := validators.Update(validator) 626 if !updated { 627 return nil, fmt.Errorf("Failed to update validator %v with voting power %d", validator.Address, v.Amount) 628 } 629 } 630 } 631 } 632 633 // Determine the Validator Size 634 //valSize := oldValSize + newValSize/2 635 valSize := oldValSize + newValSize 636 if valSize > MaximumValidatorsSize { 637 valSize = MaximumValidatorsSize 638 } else if valSize < MinimumValidatorsSize { 639 valSize = MinimumValidatorsSize 640 } 641 642 // Subtract the remaining epoch value 643 for _, v := range validators.Validators { 644 if v.RemainingEpoch > 0 { 645 v.RemainingEpoch-- 646 } 647 } 648 649 // If actual size of Validators greater than Determine Validator Size 650 // then sort the Validators with VotingPower and return the most top Validators 651 if validators.Size() > valSize { 652 // Sort the Validator Set with Amount 653 sort.Slice(validators.Validators, func(i, j int) bool { 654 // Compare with remaining epoch first then, voting power 655 if validators.Validators[i].RemainingEpoch == validators.Validators[j].RemainingEpoch { 656 return validators.Validators[i].VotingPower.Cmp(validators.Validators[j].VotingPower) == 1 657 } else { 658 return validators.Validators[i].RemainingEpoch > validators.Validators[j].RemainingEpoch 659 } 660 }) 661 // Add knockout validator to refund list 662 knockout := validators.Validators[valSize:] 663 for _, k := range knockout { 664 refund = append(refund, &tmTypes.RefundValidatorAmount{Address: common.BytesToAddress(k.Address), Amount: nil, Voteout: true}) 665 } 666 667 validators.Validators = validators.Validators[:valSize] 668 } 669 670 return refund, nil 671 } 672 673 func (epoch *Epoch) GetEpochByBlockNumber(blockNumber uint64) *Epoch { 674 675 if blockNumber >= epoch.StartBlock && blockNumber <= epoch.EndBlock { 676 return epoch 677 } 678 679 for number := epoch.Number - 1; number >= 0; number-- { 680 681 ep := loadOneEpoch(epoch.db, number, epoch.logger) 682 if ep == nil { 683 return nil 684 } 685 686 if blockNumber >= ep.StartBlock && blockNumber <= ep.EndBlock { 687 return ep 688 } 689 } 690 691 return nil 692 } 693 694 func (epoch *Epoch) Copy() *Epoch { 695 return epoch.copy(true) 696 } 697 698 func (epoch *Epoch) copy(copyPrevNext bool) *Epoch { 699 700 var previousEpoch, nextEpoch *Epoch 701 if copyPrevNext { 702 if epoch.previousEpoch != nil { 703 previousEpoch = epoch.previousEpoch.copy(false) 704 } 705 706 if epoch.nextEpoch != nil { 707 nextEpoch = epoch.nextEpoch.copy(false) 708 } 709 } 710 711 return &Epoch{ 712 mtx: epoch.mtx, 713 db: epoch.db, 714 logger: epoch.logger, 715 716 rs: epoch.rs, 717 718 Number: epoch.Number, 719 RewardPerBlock: new(big.Int).Set(epoch.RewardPerBlock), 720 StartBlock: epoch.StartBlock, 721 EndBlock: epoch.EndBlock, 722 StartTime: epoch.StartTime, 723 EndTime: epoch.EndTime, 724 BlockGenerated: epoch.BlockGenerated, 725 Status: epoch.Status, 726 Validators: epoch.Validators.Copy(), 727 validatorVoteSet: epoch.validatorVoteSet.Copy(), 728 729 previousEpoch: previousEpoch, 730 nextEpoch: nextEpoch, 731 } 732 } 733 734 func (epoch *Epoch) estimateForNextEpoch(lastBlockHeight uint64, lastBlockTime time.Time) (rewardPerBlock *big.Int, blocksOfNextEpoch uint64) { 735 736 var rewardFirstYear = epoch.rs.RewardFirstYear //20000000e+18 every year 737 var epochNumberPerYear = epoch.rs.EpochNumberPerYear //4380 738 var totalYear = epoch.rs.TotalYear //10 739 var timePerBlockOfEpoch int64 740 741 const EMERGENCY_BLOCKS_OF_NEXT_EPOCH uint64 = 100 // al least 100 blocks per epoch 742 743 zeroEpoch := loadOneEpoch(epoch.db, 0, epoch.logger) 744 initStartTime := zeroEpoch.StartTime 745 746 //from 0 year 747 thisYear := epoch.Number / epochNumberPerYear 748 nextYear := thisYear + 1 749 750 log.Infof("estimateForNextEpoch, previous epoch %v, current epoch %v, last block height %v, epoch start block %v", epoch.previousEpoch, epoch, lastBlockHeight, epoch.StartBlock) 751 752 if epoch.previousEpoch != nil { 753 log.Infof("estimateForNextEpoch previous epoch, start time %v, end time %v", epoch.previousEpoch.StartTime.UnixNano(), epoch.previousEpoch.EndTime.UnixNano()) 754 prevEpoch := epoch.previousEpoch 755 timePerBlockOfEpoch = prevEpoch.EndTime.Sub(prevEpoch.StartTime).Nanoseconds() / int64(prevEpoch.EndBlock-prevEpoch.StartBlock) 756 } else { 757 timePerBlockOfEpoch = lastBlockTime.Sub(epoch.StartTime).Nanoseconds() / int64(lastBlockHeight-epoch.StartBlock) 758 } 759 760 if timePerBlockOfEpoch == 0 { 761 timePerBlockOfEpoch = 1000000000 762 } 763 764 epochLeftThisYear := epochNumberPerYear - epoch.Number%epochNumberPerYear - 1 765 766 blocksOfNextEpoch = 0 767 768 log.Info("estimateForNextEpoch", 769 "epochLeftThisYear", epochLeftThisYear, 770 "timePerBlockOfEpoch", timePerBlockOfEpoch) 771 772 if epochLeftThisYear == 0 { //to another year 773 774 nextYearStartTime := initStartTime.AddDate(int(nextYear), 0, 0) 775 776 nextYearEndTime := nextYearStartTime.AddDate(1, 0, 0) 777 778 timeLeftNextYear := nextYearEndTime.Sub(nextYearStartTime) 779 780 epochLeftNextYear := epochNumberPerYear 781 782 epochTimePerEpochLeftNextYear := timeLeftNextYear.Nanoseconds() / int64(epochLeftNextYear) 783 784 blocksOfNextEpoch = uint64(epochTimePerEpochLeftNextYear / timePerBlockOfEpoch) 785 786 log.Info("estimateForNextEpoch 0", 787 "timePerBlockOfEpoch", timePerBlockOfEpoch, 788 "nextYearStartTime", nextYearStartTime, 789 "timeLeftNextYear", timeLeftNextYear, 790 "epochLeftNextYear", epochLeftNextYear, 791 "epochTimePerEpochLeftNextYear", epochTimePerEpochLeftNextYear, 792 "blocksOfNextEpoch", blocksOfNextEpoch) 793 794 if blocksOfNextEpoch < EMERGENCY_BLOCKS_OF_NEXT_EPOCH { 795 blocksOfNextEpoch = EMERGENCY_BLOCKS_OF_NEXT_EPOCH //make it move ahead 796 epoch.logger.Error("EstimateForNextEpoch Error: Please check the epoch_no_per_year setup in Genesis") 797 } 798 799 rewardPerEpochNextYear := calculateRewardPerEpochByYear(rewardFirstYear, int64(nextYear), int64(totalYear), int64(epochNumberPerYear)) 800 801 rewardPerBlock = new(big.Int).Div(rewardPerEpochNextYear, big.NewInt(int64(blocksOfNextEpoch))) 802 803 } else { 804 805 nextYearStartTime := initStartTime.AddDate(int(nextYear), 0, 0) 806 807 timeLeftThisYear := nextYearStartTime.Sub(lastBlockTime) 808 809 if timeLeftThisYear > 0 { 810 811 epochTimePerEpochLeftThisYear := timeLeftThisYear.Nanoseconds() / int64(epochLeftThisYear) 812 813 blocksOfNextEpoch = uint64(epochTimePerEpochLeftThisYear / timePerBlockOfEpoch) 814 815 log.Info("estimateForNextEpoch 1", 816 "timePerBlockOfEpoch", timePerBlockOfEpoch, 817 "nextYearStartTime", nextYearStartTime, 818 "timeLeftThisYear", timeLeftThisYear, 819 "epochTimePerEpochLeftThisYear", epochTimePerEpochLeftThisYear, 820 "blocksOfNextEpoch", blocksOfNextEpoch) 821 } 822 823 if blocksOfNextEpoch < EMERGENCY_BLOCKS_OF_NEXT_EPOCH { 824 blocksOfNextEpoch = EMERGENCY_BLOCKS_OF_NEXT_EPOCH //make it move ahead 825 epoch.logger.Error("EstimateForNextEpoch Error: Please check the epoch_no_per_year setup in Genesis") 826 } 827 828 log.Debugf("Current Epoch Number %v, This Year %v, Next Year %v, Epoch No Per Year %v, Epoch Left This year %v\n"+ 829 "initStartTime %v ; nextYearStartTime %v\n"+ 830 "Time Left This year %v, timePerBlockOfEpoch %v, blocksOfNextEpoch %v\n", epoch.Number, thisYear, nextYear, epochNumberPerYear, epochLeftThisYear, initStartTime, nextYearStartTime, timeLeftThisYear, timePerBlockOfEpoch, blocksOfNextEpoch) 831 832 rewardPerEpochThisYear := calculateRewardPerEpochByYear(rewardFirstYear, int64(thisYear), int64(totalYear), int64(epochNumberPerYear)) 833 834 rewardPerBlock = new(big.Int).Div(rewardPerEpochThisYear, big.NewInt(int64(blocksOfNextEpoch))) 835 836 } 837 return rewardPerBlock, blocksOfNextEpoch 838 } 839 840 func calculateRewardPerEpochByYear(rewardFirstYear *big.Int, year, totalYear, epochNumberPerYear int64) *big.Int { 841 if year > totalYear { 842 return big.NewInt(0) 843 } 844 845 return new(big.Int).Div(rewardFirstYear, big.NewInt(epochNumberPerYear)) 846 } 847 848 func (epoch *Epoch) Equals(other *Epoch, checkPrevNext bool) bool { 849 850 if (epoch == nil && other != nil) || (epoch != nil && other == nil) { 851 return false 852 } 853 854 if epoch == nil && other == nil { 855 log.Debugf("Epoch equals epoch %v, other %v", epoch, other) 856 return true 857 } 858 859 if !(epoch.Number == other.Number && epoch.RewardPerBlock.Cmp(other.RewardPerBlock) == 0 && 860 epoch.StartBlock == other.StartBlock && epoch.EndBlock == other.EndBlock && 861 epoch.Validators.Equals(other.Validators)) { 862 return false 863 } 864 865 if checkPrevNext { 866 if !epoch.previousEpoch.Equals(other.previousEpoch, false) || 867 !epoch.nextEpoch.Equals(other.nextEpoch, false) { 868 return false 869 } 870 } 871 log.Debugf("Epoch equals end, no matching") 872 return true 873 } 874 875 func (epoch *Epoch) String() string { 876 return fmt.Sprintf("Epoch : {"+ 877 "Number : %v,\n"+ 878 "RewardPerBlock : %v,\n"+ 879 "StartBlock : %v,\n"+ 880 "EndBlock : %v,\n"+ 881 "StartTime : %v,\n"+ 882 "EndTime : %v,\n"+ 883 "BlockGenerated : %v,\n"+ 884 "Status : %v,\n"+ 885 "Next Epoch : %v,\n"+ 886 "Prev Epoch : %v,\n"+ 887 "Contains RS : %v, \n"+ 888 "}", 889 epoch.Number, 890 epoch.RewardPerBlock, 891 epoch.StartBlock, 892 epoch.EndBlock, 893 epoch.StartTime, 894 epoch.EndTime, 895 epoch.BlockGenerated, 896 epoch.Status, 897 epoch.nextEpoch, 898 epoch.previousEpoch, 899 epoch.rs != nil, 900 ) 901 } 902 903 func UpdateEpochEndTime(db dbm.DB, epNumber uint64, endTime time.Time) { 904 // Load Epoch from DB 905 ep := loadOneEpoch(db, epNumber, nil) 906 if ep != nil { 907 ep.mtx.Lock() 908 defer ep.mtx.Unlock() 909 // Set End Time 910 ep.EndTime = endTime 911 // Save back to DB 912 db.SetSync(calcEpochKeyWithHeight(epNumber), ep.Bytes()) 913 } 914 } 915 916 func (epoch *Epoch) GetForbiddenDuration() time.Duration { 917 return ForbiddenDuration 918 } 919 920 // Update validator block time and set forbidden if this validator did not participate in consensus in one epoch 921 func (epoch *Epoch) UpdateForbiddenState(header *types.Header, prevHeader *types.Header, commit *tmTypes.Commit, state *state.StateDB) { 922 validators := epoch.Validators.Validators 923 height := header.Number.Uint64() 924 //forbiddenTime := prevHeader.Time 925 926 // epoch.logger.Infof("Update validator forbidden state height %v", height) 927 928 if height <= 1 || height == epoch.StartBlock { 929 return 930 } else if height == epoch.EndBlock { 931 // epoch.logger.Debugf("Update validator forbidden state, epoch end block %v", height) 932 // epoch end block set all validators mined block times 0 933 for _, v := range validators { 934 addr := common.BytesToAddress(v.Address[:]) 935 state.SetMinedBlocks(addr, common.Big0) 936 } 937 } else if height == (epoch.EndBlock - 1) { 938 epoch.logger.Debugf("Update validator forbidden state, epoch end block - 1 %v", height) 939 // epoch end block - 1, if mined block times 0, set the validator forbidden true 940 for _, v := range validators { 941 addr := common.BytesToAddress(v.Address[:]) 942 times := state.GetMinedBlocks(addr) 943 if times.Cmp(common.Big0) == 0 { 944 epoch.logger.Debugf("Update validator forbidden state, set %v forbidden, mined blocks %v, forbidden epoch %v", addr.String(), times, ForbiddenEpoch) 945 state.SetForbidden(addr, true) 946 state.SetForbiddenTime(addr, ForbiddenEpoch) 947 948 state.MarkAddressForbidden(addr) 949 } 950 } 951 } else { 952 if commit == nil || commit.BitArray == nil { 953 epoch.logger.Debugf("Update validator forbidden state seenCommit %v", commit) 954 return 955 } 956 957 // update the mined block times 958 bitMap := commit.BitArray 959 for i := uint64(0); i < bitMap.Size(); i++ { 960 if bitMap.GetIndex(i) { 961 addr := common.BytesToAddress(validators[i].Address) 962 //vObj := state.GetOrNewStateObject(addr) 963 964 times := state.GetMinedBlocks(addr) 965 newTimes := big.NewInt(0) 966 newTimes.Add(times, common.Big1) 967 968 state.SetMinedBlocks(addr, newTimes) 969 970 epoch.logger.Debugf("Update validator forbidden state, %v new mined block times %v, current times %v", addr.String(), newTimes, times) 971 } 972 } 973 } 974 975 }