github.com/okex/exchain@v1.8.0/libs/tendermint/mempool/recommended_gasprice.go (about)

     1  package mempool
     2  
     3  import (
     4  	"fmt"
     5  	"math/big"
     6  	"sort"
     7  
     8  	"github.com/okex/exchain/libs/system/trace"
     9  	cfg "github.com/okex/exchain/libs/tendermint/config"
    10  	"github.com/okex/exchain/libs/tendermint/types"
    11  )
    12  
    13  type GPOConfig struct {
    14  	Weight  int
    15  	Default *big.Int
    16  	Blocks  int
    17  }
    18  
    19  func NewGPOConfig(weight int, checkBlocks int) GPOConfig {
    20  	return GPOConfig{
    21  		Weight: weight,
    22  		// default gas price is 0.1GWei
    23  		Default: big.NewInt(100000000),
    24  		Blocks:  checkBlocks,
    25  	}
    26  }
    27  
    28  // Oracle recommends gas prices based on the content of recent blocks.
    29  type Oracle struct {
    30  	CurrentBlockGPs *types.SingleBlockGPs
    31  	// hold the gas prices of the latest few blocks
    32  	BlockGPQueue *types.BlockGPResults
    33  	lastPrice    *big.Int
    34  	weight       int
    35  }
    36  
    37  // NewOracle returns a new gasprice oracle which can recommend suitable
    38  // gasprice for newly created transaction.
    39  func NewOracle(params GPOConfig) *Oracle {
    40  	cbgp := types.NewSingleBlockGPs()
    41  	bgpq := types.NewBlockGPResults(params.Blocks)
    42  	weight := params.Weight
    43  	if weight < 0 {
    44  		weight = 0
    45  	}
    46  	if weight > 100 {
    47  		weight = 100
    48  	}
    49  	return &Oracle{
    50  		CurrentBlockGPs: cbgp,
    51  		BlockGPQueue:    bgpq,
    52  		// Note: deep copy is necessary here
    53  		lastPrice: new(big.Int).Set(params.Default),
    54  		weight:    weight,
    55  	}
    56  }
    57  
    58  func (gpo *Oracle) RecommendGP() (*big.Int, bool) {
    59  
    60  	gasUsedThreshold := cfg.DynamicConfig.GetDynamicGpMaxGasUsed()
    61  	txNumThreshold := cfg.DynamicConfig.GetDynamicGpMaxTxNum()
    62  
    63  	allTxsLen := int64(len(gpo.CurrentBlockGPs.GetAll()))
    64  	// If the current block's total gas consumption is more than gasUsedThreshold,
    65  	// or the number of tx in the current block is more than txNumThreshold,
    66  	// then we consider the chain to be congested.
    67  	isCongested := (int64(gpo.CurrentBlockGPs.GetGasUsed()) >= gasUsedThreshold) || (allTxsLen >= txNumThreshold)
    68  	trace.GetElapsedInfo().AddInfo(trace.IsCongested, fmt.Sprintf("%t", isCongested))
    69  
    70  	// If GP mode is CongestionHigherGpMode, increase the recommended gas price when the network is congested.
    71  	adoptHigherGp := (cfg.DynamicConfig.GetDynamicGpMode() == types.CongestionHigherGpMode) && isCongested
    72  
    73  	txPrices := gpo.BlockGPQueue.ExecuteSamplingBy(gpo.lastPrice, adoptHigherGp)
    74  
    75  	price := new(big.Int).Set(gpo.lastPrice)
    76  
    77  	if len(txPrices) > 0 {
    78  		sort.Sort(types.BigIntArray(txPrices))
    79  		price.Set(txPrices[(len(txPrices)-1)*gpo.weight/100])
    80  	}
    81  	gpo.lastPrice.Set(price)
    82  
    83  	trace.GetElapsedInfo().AddInfo(trace.RecommendedGP, fmt.Sprintf("%sWei", price.String()))
    84  	return price, isCongested
    85  }