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