all: set gas limit dynamically (#1945)

This commit is contained in:
Daniel Liu 2026-01-21 13:19:20 +08:00 committed by GitHub
parent c27d49c03e
commit 1f3faa5184
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 44 additions and 25 deletions

View file

@ -65,6 +65,7 @@ type constant struct {
eip1559Block *big.Int
cancunBlock *big.Int
pragueBlock *big.Int
dynamicGasLimitBlock *big.Int
trc21IssuerSMC Address
xdcxListingSMC Address
@ -100,6 +101,7 @@ var (
Eip1559Block = MainnetConstant.eip1559Block
CancunBlock = MainnetConstant.cancunBlock
PragueBlock = MainnetConstant.pragueBlock
DynamicGasLimitBlock = MainnetConstant.dynamicGasLimitBlock
TIPUpgradeReward = MainnetConstant.tipUpgradeReward
TipUpgradePenalty = MainnetConstant.tipUpgradePenalty
TIPEpochHalving = MainnetConstant.tipEpochHalving
@ -163,6 +165,7 @@ func CopyConstants(chainID uint64) {
Eip1559Block = c.eip1559Block
CancunBlock = c.cancunBlock
PragueBlock = c.pragueBlock
DynamicGasLimitBlock = c.dynamicGasLimitBlock
TIPUpgradeReward = c.tipUpgradeReward
TipUpgradePenalty = c.tipUpgradePenalty
TIPEpochHalving = c.tipEpochHalving

View file

@ -30,6 +30,7 @@ var DevnetConstant = constant{
eip1559Block: big.NewInt(32400),
cancunBlock: big.NewInt(43200),
pragueBlock: big.NewInt(math.MaxInt64),
dynamicGasLimitBlock: big.NewInt(math.MaxInt64),
tipUpgradeReward: big.NewInt(math.MaxInt64),
tipUpgradePenalty: big.NewInt(math.MaxInt64),
tipEpochHalving: big.NewInt(math.MaxInt64),

View file

@ -30,6 +30,7 @@ var localConstant = constant{
eip1559Block: big.NewInt(0),
cancunBlock: big.NewInt(0),
pragueBlock: big.NewInt(math.MaxInt64),
dynamicGasLimitBlock: big.NewInt(0),
tipUpgradeReward: big.NewInt(math.MaxInt64),
tipUpgradePenalty: big.NewInt(math.MaxInt64),
tipEpochHalving: big.NewInt(math.MaxInt64),

View file

@ -30,6 +30,7 @@ var MainnetConstant = constant{
eip1559Block: big.NewInt(math.MaxInt64),
cancunBlock: big.NewInt(math.MaxInt64),
pragueBlock: big.NewInt(math.MaxInt64),
dynamicGasLimitBlock: big.NewInt(math.MaxInt64),
tipUpgradeReward: big.NewInt(math.MaxInt64),
tipUpgradePenalty: big.NewInt(math.MaxInt64),
tipEpochHalving: big.NewInt(math.MaxInt64),

View file

@ -30,6 +30,7 @@ var TestnetConstant = constant{
eip1559Block: big.NewInt(71550000), // Target 14th Feb 2025
cancunBlock: big.NewInt(71551800),
pragueBlock: big.NewInt(math.MaxInt64),
dynamicGasLimitBlock: big.NewInt(math.MaxInt64),
tipUpgradeReward: big.NewInt(math.MaxInt64),
tipUpgradePenalty: big.NewInt(math.MaxInt64),
tipEpochHalving: big.NewInt(math.MaxInt64),

View file

@ -110,7 +110,7 @@ func init() {
func genTxRing(naccounts int) func(int, *BlockGen) {
from := 0
return func(i int, gen *BlockGen) {
gas := CalcGasLimit(gen.PrevBlock(i - 1))
gas := CalcGasLimit(gen.PrevBlock(i-1).GasLimit(), params.TargetGasLimit)
for {
gas -= params.TxGas
if gas < params.TxGas {

View file

@ -173,29 +173,22 @@ func (v *BlockValidator) ValidateLendingOrder(statedb *state.StateDB, lendingSta
return nil
}
// CalcGasLimit computes the gas limit of the next block after parent.
// This is miner strategy, not consensus protocol.
func CalcGasLimit(parent *types.Block) uint64 {
// contrib = (parentGasUsed * 3 / 2) / 1024
contrib := (parent.GasUsed() + parent.GasUsed()/2) / params.GasLimitBoundDivisor
// decay = parentGasLimit / 1024 -1
decay := parent.GasLimit()/params.GasLimitBoundDivisor - 1
/*
strategy: gasLimit of block-to-mine is set based on parent's
gasUsed value. if parentGasUsed > parentGasLimit * (2/3) then we
increase it, otherwise lower it (or leave it unchanged if it's right
at that usage) the amount increased/decreased depends on how far away
from parentGasLimit * (2/3) parentGasUsed is.
*/
limit := max(parent.GasLimit()-decay+contrib, params.MinGasLimit)
// however, if we're now below the target (TargetGasLimit) we increase the
// limit as much as we can (parentGasLimit / 1024 -1)
if limit < params.TargetGasLimit {
limit = min(parent.GasLimit() + decay, params.TargetGasLimit)
// CalcGasLimit computes the gas limit of the next block after parent. It aims
// to keep the baseline gas close to the provided target, and increase it towards
// the target if the baseline gas is lower.
func CalcGasLimit(parentGasLimit, desiredLimit uint64) uint64 {
delta := parentGasLimit/params.GasLimitBoundDivisor - 1
if desiredLimit < params.MinGasLimit {
desiredLimit = params.MinGasLimit
}
return limit
// If we're outside our allowed gas range, we try to hone towards them
if parentGasLimit < desiredLimit {
return min(parentGasLimit+delta, desiredLimit)
}
if parentGasLimit > desiredLimit {
return max(parentGasLimit-delta, desiredLimit)
}
return parentGasLimit
}
func ExtractTradingTransactions(transactions types.Transactions) ([]tradingstate.TxMatchBatch, error) {

View file

@ -293,7 +293,7 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
Difficulty: parent.Difficulty(),
UncleHash: parent.UncleHash(),
}),
GasLimit: CalcGasLimit(parent),
GasLimit: CalcGasLimit(parent.GasLimit(), params.TargetGasLimit),
Number: new(big.Int).Add(parent.Number(), common.Big1),
Time: time,
}

View file

@ -736,10 +736,14 @@ func (w *worker) commitNewWork() {
header := &types.Header{
ParentHash: parent.Hash(),
Number: num.Add(num, common.Big1),
GasLimit: params.TargetGasLimit,
Extra: w.extra,
Time: uint64(tstamp),
}
if w.config.IsDynamicGasLimitBlock(header.Number) {
header.GasLimit = core.CalcGasLimit(parent.GasLimit(), params.TargetGasLimit)
} else {
header.GasLimit = params.TargetGasLimit
}
// Set baseFee if we are on an EIP-1559 chain
header.BaseFee = eip1559.CalcBaseFee(w.config, header)

View file

@ -495,6 +495,8 @@ type ChainConfig struct {
CancunBlock *big.Int `json:"cancunBlock,omitempty"`
PragueBlock *big.Int `json:"pragueBlock,omitempty"`
DynamicGasLimitBlock *big.Int `json:"dynamicGasLimitBlock,omitempty"` // Dynamic gas limit adjustment algorithm activation block (nil = no fork)
// Various consensus engines
Ethash *EthashConfig `json:"ethash,omitempty"`
Clique *CliqueConfig `json:"clique,omitempty"`
@ -860,6 +862,9 @@ func (c *ChainConfig) String() string {
if c.PragueBlock != nil {
result += fmt.Sprintf(", PragueBlock: %v", c.PragueBlock)
}
if c.DynamicGasLimitBlock != nil {
result += fmt.Sprintf(", DynamicGasLimitBlock: %v", c.DynamicGasLimitBlock)
}
if c.XDPoS != nil {
result += fmt.Sprintf(", %s", c.XDPoS.String())
}
@ -907,6 +912,10 @@ func (c *ChainConfig) Description() string {
if c.PragueBlock != nil {
pragueBlock = c.PragueBlock
}
dynamicGasLimitBlock := common.DynamicGasLimitBlock
if c.DynamicGasLimitBlock != nil {
dynamicGasLimitBlock = c.DynamicGasLimitBlock
}
var banner = "Chain configuration:\n"
banner += fmt.Sprintf(" - ChainID: %-8v\n", c.ChainID)
@ -939,6 +948,7 @@ func (c *ChainConfig) Description() string {
banner += fmt.Sprintf(" - Eip1559: %-8v\n", eip1559Block)
banner += fmt.Sprintf(" - Cancun: %-8v\n", cancunBlock)
banner += fmt.Sprintf(" - Prague: %-8v\n", pragueBlock)
banner += fmt.Sprintf(" - DynamicGasLimitBlock: %-8v\n", dynamicGasLimitBlock)
banner += fmt.Sprintf(" - TIPUpgradeReward: %-8v\n", common.TIPUpgradeReward)
banner += fmt.Sprintf(" - TipUpgradePenalty: %-8v\n", common.TipUpgradePenalty)
banner += fmt.Sprintf(" - TIPEpochHalving: %-8v\n", common.TIPEpochHalving)
@ -1024,6 +1034,11 @@ func (c *ChainConfig) IsPrague(num *big.Int) bool {
return isForked(common.PragueBlock, num) || isForked(c.PragueBlock, num)
}
// IsDynamicGasLimitBlock returns whether num is either equal to the DynamicGasLimitBlock fork block or greater.
func (c *ChainConfig) IsDynamicGasLimitBlock(num *big.Int) bool {
return isForked(common.DynamicGasLimitBlock, num) || isForked(c.DynamicGasLimitBlock, num)
}
func (c *ChainConfig) IsTIP2019(num *big.Int) bool {
return isForked(common.TIP2019Block, num)
}