Skip to content

Commit

Permalink
Merge PR: recommend gp bug fix (#2744)
Browse files Browse the repository at this point in the history
* gp bug fix

* modify code

* add flag DynamicGpAdaptUncongest

* modify ut

* adapt congest

* bug fix

* code optimize

Co-authored-by: KamiD <[email protected]>
LeoGuo621 and KamiD authored Nov 19, 2022
1 parent 517cd7f commit 5039f2e
Showing 6 changed files with 478 additions and 74 deletions.
94 changes: 80 additions & 14 deletions app/config/config.go
Original file line number Diff line number Diff line change
@@ -53,6 +53,12 @@ type OecConfig struct {
dynamicGpWeight int
// dynamic-gp-check-blocks
dynamicGpCheckBlocks int
// dynamic-gp-adapt-uncongest
dynamicGpAdaptUncongest bool
// dynamic-gp-adapt-congest
dynamicGpAdaptCongest bool
// dynamic-gp-coefficient
dynamicGpCoefficient int

// consensus.timeout_propose
csTimeoutPropose time.Duration
@@ -95,20 +101,23 @@ type OecConfig struct {
const (
FlagEnableDynamic = "config.enable-dynamic"

FlagMempoolRecheck = "mempool.recheck"
FlagMempoolForceRecheckGap = "mempool.force_recheck_gap"
FlagMempoolSize = "mempool.size"
FlagMempoolFlush = "mempool.flush"
FlagMaxTxNumPerBlock = "mempool.max_tx_num_per_block"
FlagMaxGasUsedPerBlock = "mempool.max_gas_used_per_block"
FlagNodeKeyWhitelist = "mempool.node_key_whitelist"
FlagMempoolCheckTxCost = "mempool.check_tx_cost"
FlagGasLimitBuffer = "gas-limit-buffer"
FlagEnableDynamicGp = "enable-dynamic-gp"
FlagDynamicGpWeight = "dynamic-gp-weight"
FlagDynamicGpCheckBlocks = "dynamic-gp-check-blocks"
FlagEnableWrappedTx = "enable-wtx"
FlagSentryAddrs = "p2p.sentry_addrs"
FlagMempoolRecheck = "mempool.recheck"
FlagMempoolForceRecheckGap = "mempool.force_recheck_gap"
FlagMempoolSize = "mempool.size"
FlagMempoolFlush = "mempool.flush"
FlagMaxTxNumPerBlock = "mempool.max_tx_num_per_block"
FlagMaxGasUsedPerBlock = "mempool.max_gas_used_per_block"
FlagNodeKeyWhitelist = "mempool.node_key_whitelist"
FlagMempoolCheckTxCost = "mempool.check_tx_cost"
FlagGasLimitBuffer = "gas-limit-buffer"
FlagEnableDynamicGp = "enable-dynamic-gp"
FlagDynamicGpWeight = "dynamic-gp-weight"
FlagDynamicGpCheckBlocks = "dynamic-gp-check-blocks"
FlagDynamicGpAdaptUncongest = "dynamic-gp-adapt-uncongest"
FlagDynamicGpAdaptCongest = "dynamic-gp-adapt-congest"
FlagDynamicGpCoefficient = "dynamic-gp-coefficient"
FlagEnableWrappedTx = "enable-wtx"
FlagSentryAddrs = "p2p.sentry_addrs"

FlagCsTimeoutPropose = "consensus.timeout_propose"
FlagCsTimeoutProposeDelta = "consensus.timeout_propose_delta"
@@ -224,6 +233,9 @@ func (c *OecConfig) loadFromConfig() {
c.SetEnableDynamicGp(viper.GetBool(FlagEnableDynamicGp))
c.SetDynamicGpWeight(viper.GetInt(FlagDynamicGpWeight))
c.SetDynamicGpCheckBlocks(viper.GetInt(FlagDynamicGpCheckBlocks))
c.SetDynamicGpCoefficient(viper.GetInt(FlagDynamicGpCoefficient))
c.SetDynamicGpAdaptCongest(viper.GetBool(FlagDynamicGpAdaptCongest))
c.SetDynamicGpAdaptUncongest(viper.GetBool(FlagDynamicGpAdaptUncongest))
c.SetCsTimeoutPropose(viper.GetDuration(FlagCsTimeoutPropose))
c.SetCsTimeoutProposeDelta(viper.GetDuration(FlagCsTimeoutProposeDelta))
c.SetCsTimeoutPrevote(viper.GetDuration(FlagCsTimeoutPrevote))
@@ -274,6 +286,10 @@ func (c *OecConfig) format() string {
gas-limit-buffer: %d
enable-dynamic-gp: %v
dynamic-gp-weight: %d
dynamic-gp-check-blocks: %d
dynamic-gp-adapt-uncongest: %v
dynamic-gp-adapt-congest: %v
dynamic-gp-adapt-coefficient: %d
consensus.timeout_propose: %s
consensus.timeout_propose_delta: %s
@@ -296,6 +312,10 @@ func (c *OecConfig) format() string {
c.GetGasLimitBuffer(),
c.GetEnableDynamicGp(),
c.GetDynamicGpWeight(),
c.GetDynamicGpCheckBlocks(),
c.GetDynamicGpAdaptUncongest(),
c.GetDynamicGpAdaptCongest(),
c.GetDynamicGpCoefficient(),
c.GetCsTimeoutPropose(),
c.GetCsTimeoutProposeDelta(),
c.GetCsTimeoutPrevote(),
@@ -390,6 +410,24 @@ func (c *OecConfig) update(key, value interface{}) {
return
}
c.SetDynamicGpCheckBlocks(r)
case FlagDynamicGpAdaptUncongest:
r, err := strconv.ParseBool(v)
if err != nil {
return
}
c.SetDynamicGpAdaptUncongest(r)
case FlagDynamicGpAdaptCongest:
r, err := strconv.ParseBool(v)
if err != nil {
return
}
c.SetDynamicGpAdaptCongest(r)
case FlagDynamicGpCoefficient:
r, err := strconv.Atoi(v)
if err != nil {
return
}
c.SetDynamicGpCoefficient(r)
case FlagCsTimeoutPropose:
r, err := time.ParseDuration(v)
if err != nil {
@@ -628,6 +666,18 @@ func (c *OecConfig) SetDynamicGpWeight(value int) {
c.dynamicGpWeight = value
}

func (c *OecConfig) GetDynamicGpCoefficient() int {
return c.dynamicGpCoefficient
}
func (c *OecConfig) SetDynamicGpCoefficient(value int) {
if value <= 0 {
value = 1
} else if value > 100 {
value = 100
}
c.dynamicGpCoefficient = value
}

func (c *OecConfig) GetDynamicGpCheckBlocks() int {
return c.dynamicGpCheckBlocks
}
@@ -641,6 +691,22 @@ func (c *OecConfig) SetDynamicGpCheckBlocks(value int) {
c.dynamicGpCheckBlocks = value
}

func (c *OecConfig) SetDynamicGpAdaptUncongest(value bool) {
c.dynamicGpAdaptUncongest = value
}

func (c *OecConfig) GetDynamicGpAdaptUncongest() bool {
return c.dynamicGpAdaptUncongest
}

func (c *OecConfig) SetDynamicGpAdaptCongest(value bool) {
c.dynamicGpAdaptCongest = value
}

func (c *OecConfig) GetDynamicGpAdaptCongest() bool {
return c.dynamicGpAdaptCongest
}

func (c *OecConfig) GetCsTimeoutPropose() time.Duration {
return c.csTimeoutPropose
}
40 changes: 27 additions & 13 deletions app/gasprice/gasprice.go
Original file line number Diff line number Diff line change
@@ -5,14 +5,17 @@ import (
"sort"

"github.com/ethereum/go-ethereum/params"
"github.com/spf13/viper"

appconfig "github.com/okex/exchain/app/config"
"github.com/okex/exchain/app/types"
"github.com/okex/exchain/libs/cosmos-sdk/server"
sdk "github.com/okex/exchain/libs/cosmos-sdk/types"
)

var (
maxPrice = big.NewInt(500 * params.GWei)
defaultPrice = big.NewInt(params.GWei / 10)
defaultPrice = getDefaultGasPrice()
)

type GPOConfig struct {
@@ -64,29 +67,40 @@ func NewOracle(params GPOConfig) *Oracle {

func (gpo *Oracle) RecommendGP() *big.Int {
maxGasUsed := appconfig.GetOecConfig().GetMaxGasUsedPerBlock()
// If maxGasUsed is not negative and the current block's total gas consumption is
// less than 80% of it, then we consider the chain to be uncongested and return defaultPrice.
if maxGasUsed > 0 && gpo.CurrentBlockGPs.GetGasUsed() < uint64(maxGasUsed*80/100) {
return defaultPrice
}
// If the number of tx in the current block is less than the MaxTxNumPerBlock in mempool config,
// the default gas price is returned.
allGPsLen := int64(len(gpo.CurrentBlockGPs.GetAll()))
maxTxNum := appconfig.GetOecConfig().GetMaxTxNumPerBlock()
if allGPsLen < maxTxNum {
return defaultPrice
}
allTxsLen := int64(len(gpo.CurrentBlockGPs.GetAll()))
// If maxGasUsed is not negative and the current block's total gas consumption is more than 80% of it,
// or the number of tx in the current block is more than 80% of MaxTxNumPerBlock in mempool config,
// then we consider the chain to be congested.
isCongested := (gpo.CurrentBlockGPs.GetGasUsed() >= uint64(maxGasUsed*80/100)) || (allTxsLen >= maxTxNum*80/100)

adoptHigherGp := appconfig.GetOecConfig().GetDynamicGpAdaptCongest() && isCongested

txPrices := gpo.BlockGPQueue.ExecuteSamplingBy(gpo.lastPrice)
txPrices := gpo.BlockGPQueue.ExecuteSamplingBy(gpo.lastPrice, adoptHigherGp)

if appconfig.GetOecConfig().GetDynamicGpAdaptUncongest() && !isCongested {
// If network is uncongested, return default gas price.
gpo.lastPrice = defaultPrice
return defaultPrice
}
price := gpo.lastPrice
if len(txPrices) > 0 {
sort.Sort(types.BigIntArray(txPrices))
price = txPrices[(len(txPrices)-1)*gpo.weight/100]
}

if price.Cmp(maxPrice) > 0 {
price = new(big.Int).Set(maxPrice)
}
gpo.lastPrice = price
return price
}

func getDefaultGasPrice() *big.Int {
gasPrices, err := sdk.ParseDecCoins(viper.GetString(server.FlagMinGasPrices))
if err == nil && gasPrices != nil && len(gasPrices) > 0 {
return gasPrices[0].Amount.BigInt()
}
//return the default gas price : DefaultGasPrice
return sdk.NewDecFromBigIntWithPrec(big.NewInt(1), sdk.Precision/2+1).BigInt()
}
Loading

0 comments on commit 5039f2e

Please sign in to comment.