diff --git a/common/constants.all.go b/common/constants.all.go index 52d432aee9..4d40d6560d 100644 --- a/common/constants.all.go +++ b/common/constants.all.go @@ -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 diff --git a/common/constants.devnet.go b/common/constants.devnet.go index 9fd3f42186..37dcd6beb0 100644 --- a/common/constants.devnet.go +++ b/common/constants.devnet.go @@ -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), diff --git a/common/constants.local.go b/common/constants.local.go index a5a5e804e4..df847d8fd4 100644 --- a/common/constants.local.go +++ b/common/constants.local.go @@ -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), diff --git a/common/constants.mainnet.go b/common/constants.mainnet.go index 8498744d3c..d08f28fe6c 100644 --- a/common/constants.mainnet.go +++ b/common/constants.mainnet.go @@ -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), diff --git a/common/constants.testnet.go b/common/constants.testnet.go index b873419381..d581af4df6 100644 --- a/common/constants.testnet.go +++ b/common/constants.testnet.go @@ -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), diff --git a/core/bench_test.go b/core/bench_test.go index fe7d73a4c6..f0c206871c 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -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 { diff --git a/core/block_validator.go b/core/block_validator.go index cef59389ac..82460b804b 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -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) { diff --git a/core/chain_makers.go b/core/chain_makers.go index 2d8085c4bd..ebbd60a043 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -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, } diff --git a/miner/worker.go b/miner/worker.go index 17aad92588..5fa6f217b4 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -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) diff --git a/params/config.go b/params/config.go index 4fe299632b..87cee65e9e 100644 --- a/params/config.go +++ b/params/config.go @@ -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) }