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  }