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  }