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