diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index a84e5700a0..e91504c852 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1240,24 +1240,31 @@ func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) { } } -func setDurationLimit(ctx *cli.Context, cfg *ethconfig.Config) { +func setConsensusEngineConfig(ctx *cli.Context, cfg *ethconfig.Config) { if cfg.ConsensusEngine == "blake3" { // Override any default configs for hard coded networks. switch { case ctx.GlobalBool(ColosseumFlag.Name): cfg.Blake3Pow.DurationLimit = params.DurationLimit + cfg.Blake3Pow.GasCeil = params.ColosseumGasCeil case ctx.GlobalBool(GardenFlag.Name): cfg.Blake3Pow.DurationLimit = params.GardenDurationLimit + cfg.Blake3Pow.GasCeil = params.GardenGasCeil case ctx.GlobalBool(OrchardFlag.Name): cfg.Blake3Pow.DurationLimit = params.OrchardDurationLimit + cfg.Blake3Pow.GasCeil = params.OrchardGasCeil case ctx.GlobalBool(LighthouseFlag.Name): cfg.Blake3Pow.DurationLimit = params.LighthouseDurationLimit + cfg.Blake3Pow.GasCeil = params.LighthouseGasCeil case ctx.GlobalBool(LocalFlag.Name): cfg.Blake3Pow.DurationLimit = params.LocalDurationLimit + cfg.Blake3Pow.GasCeil = params.LocalGasCeil case ctx.GlobalBool(DeveloperFlag.Name): cfg.Blake3Pow.DurationLimit = params.DurationLimit + cfg.Blake3Pow.GasCeil = params.LocalGasCeil default: cfg.Blake3Pow.DurationLimit = params.DurationLimit + cfg.Blake3Pow.GasCeil = params.GasCeil } } else { @@ -1265,18 +1272,25 @@ func setDurationLimit(ctx *cli.Context, cfg *ethconfig.Config) { switch { case ctx.GlobalBool(ColosseumFlag.Name): cfg.Progpow.DurationLimit = params.DurationLimit + cfg.Progpow.GasCeil = params.ColosseumGasCeil case ctx.GlobalBool(GardenFlag.Name): cfg.Progpow.DurationLimit = params.GardenDurationLimit + cfg.Progpow.GasCeil = params.GardenGasCeil case ctx.GlobalBool(OrchardFlag.Name): cfg.Progpow.DurationLimit = params.OrchardDurationLimit + cfg.Progpow.GasCeil = params.OrchardGasCeil case ctx.GlobalBool(LighthouseFlag.Name): cfg.Progpow.DurationLimit = params.LighthouseDurationLimit + cfg.Progpow.GasCeil = params.LighthouseGasCeil case ctx.GlobalBool(LocalFlag.Name): cfg.Progpow.DurationLimit = params.LocalDurationLimit + cfg.Progpow.GasCeil = params.LocalGasCeil case ctx.GlobalBool(DeveloperFlag.Name): cfg.Progpow.DurationLimit = params.DurationLimit + cfg.Progpow.GasCeil = params.LocalGasCeil default: cfg.Progpow.DurationLimit = params.DurationLimit + cfg.Progpow.GasCeil = params.GasCeil } } @@ -1425,7 +1439,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { } else { cfg.ConsensusEngine = "progpow" } - setDurationLimit(ctx, cfg) + setConsensusEngineConfig(ctx, cfg) setWhitelist(ctx, cfg) diff --git a/consensus/blake3pow/blake3pow.go b/consensus/blake3pow/blake3pow.go index f5ea303a62..2cd4f16dc8 100644 --- a/consensus/blake3pow/blake3pow.go +++ b/consensus/blake3pow/blake3pow.go @@ -43,6 +43,8 @@ type Config struct { DurationLimit *big.Int + GasCeil uint64 + // When set, notifications sent by the remote sealer will // be block header JSON objects instead of work package arrays. NotifyFull bool diff --git a/consensus/blake3pow/consensus.go b/consensus/blake3pow/consensus.go index 24f7d5a651..f5844c537b 100644 --- a/consensus/blake3pow/consensus.go +++ b/consensus/blake3pow/consensus.go @@ -301,8 +301,10 @@ func (blake3pow *Blake3pow) verifyHeader(chain consensus.ChainHeaderReader, head } // Verify the block's gas usage and verify the base fee. // Verify that the gas limit remains within allowed bounds - if err := misc.VerifyGaslimit(parent.GasLimit(), header.GasLimit()); err != nil { - return err + expectedGasLimit := core.CalcGasLimit(parent, blake3pow.config.GasCeil) + if expectedGasLimit != header.GasLimit() { + return fmt.Errorf("invalid gasLimit: have %d, want %d", + header.GasLimit(), expectedGasLimit) } // Verify the header is not malformed if header.BaseFee() == nil { diff --git a/consensus/misc/gaslimit.go b/consensus/misc/gaslimit.go deleted file mode 100644 index 24afc685e8..0000000000 --- a/consensus/misc/gaslimit.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2021 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package misc - -import ( - "errors" - "fmt" - - "github.com/dominant-strategies/go-quai/params" -) - -// VerifyGaslimit verifies the header gas limit according increase/decrease -// in relation to the parent gas limit. -func VerifyGaslimit(parentGasLimit, headerGasLimit uint64) error { - // Verify that the gas limit remains within allowed bounds - diff := int64(parentGasLimit) - int64(headerGasLimit) - if diff < 0 { - diff *= -1 - } - limit := parentGasLimit / params.GasLimitBoundDivisor - if uint64(diff) >= limit { - return fmt.Errorf("invalid gas limit: have %d, want %d +-= %d", headerGasLimit, parentGasLimit, limit-1) - } - if headerGasLimit < params.MinGasLimit { - return errors.New("invalid gas limit below 5000") - } - return nil -} diff --git a/consensus/progpow/consensus.go b/consensus/progpow/consensus.go index 9dc8f5702b..5327102d24 100644 --- a/consensus/progpow/consensus.go +++ b/consensus/progpow/consensus.go @@ -300,8 +300,10 @@ func (progpow *Progpow) verifyHeader(chain consensus.ChainHeaderReader, header, } // Verify the block's gas usage and verify the base fee. // Verify that the gas limit remains within allowed bounds - if err := misc.VerifyGaslimit(parent.GasLimit(), header.GasLimit()); err != nil { - return err + expectedGasLimit := core.CalcGasLimit(parent, progpow.config.GasCeil) + if expectedGasLimit != header.GasLimit() { + return fmt.Errorf("invalid gasLimit: have %d, want %d", + header.GasLimit(), expectedGasLimit) } // Verify the header is not malformed if header.BaseFee() == nil { diff --git a/consensus/progpow/progpow.go b/consensus/progpow/progpow.go index 0a2b95008c..3b62db7043 100644 --- a/consensus/progpow/progpow.go +++ b/consensus/progpow/progpow.go @@ -157,6 +157,7 @@ type Config struct { CachesOnDisk int CachesLockMmap bool DurationLimit *big.Int + GasCeil uint64 // When set, notifications sent by the remote sealer will // be block header JSON objects instead of work package arrays. diff --git a/core/block_validator.go b/core/block_validator.go index 3226bc2e48..0c905f0313 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -144,25 +144,42 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD // 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 { +func CalcGasLimit(parent *types.Header, gasCeil uint64) uint64 { + + parentGasLimit := parent.GasLimit() + delta := parentGasLimit/params.GasLimitBoundDivisor - 1 limit := parentGasLimit - if desiredLimit < params.MinGasLimit { + + var desiredLimit uint64 + percentGasUsed := parent.GasUsed() * 100 / parent.GasLimit() + if percentGasUsed > params.PercentGasUsedThreshold { + desiredLimit = CalcGasCeil(parent.NumberU64(), gasCeil) + if desiredLimit > gasCeil { + desiredLimit = gasCeil + } + if limit+delta > desiredLimit { + return desiredLimit + } else { + return limit + delta + } + } else { desiredLimit = params.MinGasLimit - } - // If we're outside our allowed gas range, we try to hone towards them - if limit < desiredLimit { - limit = parentGasLimit + delta - if limit > desiredLimit { - limit = desiredLimit + if limit-delta/2 < desiredLimit { + return desiredLimit + } else { + return limit - delta/2 } - return limit } - if limit > desiredLimit { - limit = parentGasLimit - delta - if limit < desiredLimit { - limit = desiredLimit - } +} + +func CalcGasCeil(blockNumber uint64, gasCeil uint64) uint64 { + if blockNumber < params.GasLimitStepOneBlockThreshold { + return gasCeil / 4 + } else if blockNumber < params.GasLimitStepTwoBlockThreshold { + return gasCeil / 2 + } else if blockNumber < params.GasLimitStepThreeBlockThreshold { + return gasCeil * 3 / 4 } - return limit + return gasCeil } diff --git a/core/slice.go b/core/slice.go index 00fb3d30c6..fa33f05818 100644 --- a/core/slice.go +++ b/core/slice.go @@ -323,7 +323,7 @@ func (sl *Slice) Append(header *types.Header, domPendingHeader *types.Header, do log.Info("times during sub append:", "t6_1:", time6_1, "t6_2:", time6_2, "t6_3:", time6_3) log.Info("Appended new block", "number", block.Header().Number(), "hash", block.Hash(), "difficulty", block.Header().Difficulty(), - "uncles", len(block.Uncles()), "txs", len(block.Transactions()), "etxs", len(block.ExtTransactions()), "gas", block.GasUsed(), + "uncles", len(block.Uncles()), "txs", len(block.Transactions()), "etxs", len(block.ExtTransactions()), "gas", block.GasUsed(), "gasLimit", block.GasLimit(), "root", block.Root(), "order", order, "location", block.Header().Location(), diff --git a/core/worker.go b/core/worker.go index d58a4fe0a1..b5f18e0c2b 100644 --- a/core/worker.go +++ b/core/worker.go @@ -881,12 +881,7 @@ func (w *worker) fillTransactions(interrupt *int32, env *environment, block *typ // into the given sealing block. The transaction selection and ordering strategy can // be customized with the plugin in the future. func (w *worker) adjustGasLimit(interrupt *int32, env *environment, parent *types.Block) { - percentGasUsed := parent.GasUsed() * 100 / parent.GasLimit() - if percentGasUsed > params.PercentGasUsedThreshold { - env.header.SetGasLimit(CalcGasLimit(parent.GasLimit(), w.config.GasCeil)) - } else { - env.header.SetGasLimit(CalcGasLimit(parent.GasLimit(), w.config.GasFloor)) - } + env.header.SetGasLimit(CalcGasLimit(parent.Header(), w.config.GasCeil)) } // ComputeManifestHash given a header computes the manifest hash for the header diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 13afbbf112..d0e8b9133b 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -181,6 +181,7 @@ func CreateProgpowConsensusEngine(stack *node.Node, chainConfig *params.ChainCon PowMode: config.PowMode, NotifyFull: config.NotifyFull, DurationLimit: config.DurationLimit, + GasCeil: config.GasCeil, }, notify, noverify) engine.SetThreads(-1) // Disable CPU mining return engine @@ -201,6 +202,7 @@ func CreateBlake3ConsensusEngine(stack *node.Node, chainConfig *params.ChainConf PowMode: config.PowMode, NotifyFull: config.NotifyFull, DurationLimit: config.DurationLimit, + GasCeil: config.GasCeil, }, notify, noverify) engine.SetThreads(-1) // Disable CPU mining return engine diff --git a/params/protocol_params.go b/params/protocol_params.go index 172e6a687c..ce9f445170 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -23,10 +23,13 @@ import ( ) const ( - GasLimitBoundDivisor uint64 = 1024 // The bound divisor of the gas limit, used in update calculations. - PercentGasUsedThreshold uint64 = 95 // Percent Gas used threshold at which the gas limit adjusts - MinGasLimit uint64 = 5000000 // Minimum the gas limit may ever be. - GenesisGasLimit uint64 = 5000000 // Gas limit of the Genesis block. + GasLimitBoundDivisor uint64 = 1024 // The bound divisor of the gas limit, used in update calculations. + PercentGasUsedThreshold uint64 = 50 // Percent Gas used threshold at which the gas limit adjusts + GasLimitStepOneBlockThreshold uint64 = 150000 + GasLimitStepTwoBlockThreshold uint64 = 300000 + GasLimitStepThreeBlockThreshold uint64 = 450000 + MinGasLimit uint64 = 5000000 // Minimum the gas limit may ever be. + GenesisGasLimit uint64 = 5000000 // Gas limit of the Genesis block. MaximumExtraDataSize uint64 = 32 // Maximum size extra data may be after Genesis. ExpByteGas uint64 = 10 // Times ceil(log256(exponent)) for the EXP instruction. @@ -138,7 +141,8 @@ const ( ) var ( - ColosseumGasCeil uint64 = 160000000 + GasCeil uint64 = 20000000 + ColosseumGasCeil uint64 = 110000000 GardenGasCeil uint64 = 160000000 OrchardGasCeil uint64 = 50000000 LighthouseGasCeil uint64 = 160000000