github.com/ava-labs/avalanchego@v1.11.11/vms/platformvm/state/chain_time_helpers.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package state
     5  
     6  import (
     7  	"fmt"
     8  	"time"
     9  
    10  	"github.com/ava-labs/avalanchego/database"
    11  	"github.com/ava-labs/avalanchego/utils/timer/mockable"
    12  	"github.com/ava-labs/avalanchego/vms/components/gas"
    13  	"github.com/ava-labs/avalanchego/vms/platformvm/config"
    14  	"github.com/ava-labs/avalanchego/vms/platformvm/txs/fee"
    15  )
    16  
    17  func NextBlockTime(state Chain, clk *mockable.Clock) (time.Time, bool, error) {
    18  	var (
    19  		timestamp  = clk.Time()
    20  		parentTime = state.GetTimestamp()
    21  	)
    22  	if parentTime.After(timestamp) {
    23  		timestamp = parentTime
    24  	}
    25  	// [timestamp] = max(now, parentTime)
    26  
    27  	nextStakerChangeTime, err := GetNextStakerChangeTime(state)
    28  	if err != nil {
    29  		return time.Time{}, false, fmt.Errorf("failed getting next staker change time: %w", err)
    30  	}
    31  
    32  	// timeWasCapped means that [timestamp] was reduced to [nextStakerChangeTime]
    33  	timeWasCapped := !timestamp.Before(nextStakerChangeTime)
    34  	if timeWasCapped {
    35  		timestamp = nextStakerChangeTime
    36  	}
    37  	// [timestamp] = min(max(now, parentTime), nextStakerChangeTime)
    38  	return timestamp, timeWasCapped, nil
    39  }
    40  
    41  // GetNextStakerChangeTime returns the next time a staker will be either added
    42  // or removed to/from the current validator set.
    43  func GetNextStakerChangeTime(state Chain) (time.Time, error) {
    44  	currentStakerIterator, err := state.GetCurrentStakerIterator()
    45  	if err != nil {
    46  		return time.Time{}, err
    47  	}
    48  	defer currentStakerIterator.Release()
    49  
    50  	pendingStakerIterator, err := state.GetPendingStakerIterator()
    51  	if err != nil {
    52  		return time.Time{}, err
    53  	}
    54  	defer pendingStakerIterator.Release()
    55  
    56  	hasCurrentStaker := currentStakerIterator.Next()
    57  	hasPendingStaker := pendingStakerIterator.Next()
    58  	switch {
    59  	case hasCurrentStaker && hasPendingStaker:
    60  		nextCurrentTime := currentStakerIterator.Value().NextTime
    61  		nextPendingTime := pendingStakerIterator.Value().NextTime
    62  		if nextCurrentTime.Before(nextPendingTime) {
    63  			return nextCurrentTime, nil
    64  		}
    65  		return nextPendingTime, nil
    66  	case hasCurrentStaker:
    67  		return currentStakerIterator.Value().NextTime, nil
    68  	case hasPendingStaker:
    69  		return pendingStakerIterator.Value().NextTime, nil
    70  	default:
    71  		return time.Time{}, database.ErrNotFound
    72  	}
    73  }
    74  
    75  // PickFeeCalculator creates either a static or a dynamic fee calculator,
    76  // depending on the active upgrade.
    77  //
    78  // PickFeeCalculator does not modify [state].
    79  func PickFeeCalculator(cfg *config.Config, state Chain) fee.Calculator {
    80  	timestamp := state.GetTimestamp()
    81  	if !cfg.UpgradeConfig.IsEtnaActivated(timestamp) {
    82  		return NewStaticFeeCalculator(cfg, timestamp)
    83  	}
    84  
    85  	feeState := state.GetFeeState()
    86  	gasPrice := gas.CalculatePrice(
    87  		cfg.DynamicFeeConfig.MinPrice,
    88  		feeState.Excess,
    89  		cfg.DynamicFeeConfig.ExcessConversionConstant,
    90  	)
    91  	return fee.NewDynamicCalculator(
    92  		cfg.DynamicFeeConfig.Weights,
    93  		gasPrice,
    94  	)
    95  }
    96  
    97  // NewStaticFeeCalculator creates a static fee calculator, with the config set
    98  // to either the pre-AP3 or post-AP3 config.
    99  func NewStaticFeeCalculator(cfg *config.Config, timestamp time.Time) fee.Calculator {
   100  	config := cfg.StaticFeeConfig
   101  	if !cfg.UpgradeConfig.IsApricotPhase3Activated(timestamp) {
   102  		config.CreateSubnetTxFee = cfg.CreateAssetTxFee
   103  		config.CreateBlockchainTxFee = cfg.CreateAssetTxFee
   104  	}
   105  	return fee.NewStaticCalculator(config)
   106  }