Skip to content

Commit

Permalink
configurable gas limit (#1448)
Browse files Browse the repository at this point in the history
Add the ability to configure/change the gasLimit at different block heights using transitions.

```
"transitions": [{ 
  "miner.gasLimit": 10000
}]
```

Fixes #1434

Co-authored-by: Antony Denyer <git@antonydenyer.co.uk>
  • Loading branch information
baptiste-b-pegasys and antonydenyer committed Jul 19, 2022
1 parent 616f665 commit 11bd12f
Show file tree
Hide file tree
Showing 13 changed files with 45 additions and 21 deletions.
4 changes: 2 additions & 2 deletions cmd/puppeth/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ func newAlethGenesisSpec(network string, genesis *core.Genesis) (*alethGenesisSp
spec.Params.NetworkID = (hexutil.Uint64)(genesis.Config.ChainID.Uint64())
spec.Params.ChainID = (hexutil.Uint64)(genesis.Config.ChainID.Uint64())
spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize)
spec.Params.MinGasLimit = (hexutil.Uint64)(params.MinGasLimit)
spec.Params.MinGasLimit = (hexutil.Uint64)(params.DefaultMinGasLimit)
spec.Params.MaxGasLimit = (hexutil.Uint64)(math.MaxInt64)
spec.Params.MinimumDifficulty = (*hexutil.Big)(params.MinimumDifficulty)
spec.Params.DifficultyBoundDivisor = (*math2.HexOrDecimal256)(params.DifficultyBoundDivisor)
Expand Down Expand Up @@ -413,7 +413,7 @@ func newParityChainSpec(network string, genesis *core.Genesis, bootnodes []strin
spec.setIstanbul(num)
}
spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize)
spec.Params.MinGasLimit = (hexutil.Uint64)(params.MinGasLimit)
spec.Params.MinGasLimit = (hexutil.Uint64)(params.DefaultMinGasLimit)
spec.Params.GasLimitBoundDivisor = (math2.HexOrDecimal64)(params.GasLimitBoundDivisor)
spec.Params.NetworkID = (hexutil.Uint64)(genesis.Config.ChainID.Uint64())
spec.Params.ChainID = (hexutil.Uint64)(genesis.Config.ChainID.Uint64())
Expand Down
2 changes: 1 addition & 1 deletion consensus/istanbul/backend/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func makeHeader(parent *types.Block, config *istanbul.Config) *types.Header {
header := &types.Header{
ParentHash: parent.Hash(),
Number: blockNumber,
GasLimit: core.CalcGasLimit(parent, parent.GasLimit(), parent.GasLimit()),
GasLimit: core.CalcGasLimit(parent, parent.GasLimit(), parent.GasLimit(), parent.GasLimit()),
GasUsed: 0,
Time: parent.Time() + config.GetConfig(blockNumber).BlockPeriod,
Difficulty: istanbulcommon.DefaultDifficulty,
Expand Down
2 changes: 1 addition & 1 deletion core/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func genTxRing(naccounts int) func(int, *BlockGen) {
from := 0
return func(i int, gen *BlockGen) {
block := gen.PrevBlock(i - 1)
gas := CalcGasLimit(block, block.GasLimit(), block.GasLimit())
gas := CalcGasLimit(block, block.GasLimit(), block.GasLimit(), block.GasLimit())
for {
gas -= params.TxGas
if gas < params.TxGas {
Expand Down
6 changes: 3 additions & 3 deletions core/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD
// to keep the baseline gas above the provided floor, and increase it towards the
// ceil if the blocks are full. If the ceil is exceeded, it will always decrease
// the gas allowance.
func CalcGasLimit(parent *types.Block, gasFloor, gasCeil uint64) uint64 {
func CalcGasLimit(parent *types.Block, minGasLimit, gasFloor, gasCeil uint64) uint64 {
// contrib = (parentGasUsed * 3 / 2) / 4096
contrib := (parent.GasUsed() + parent.GasUsed()/2) / params.GasLimitBoundDivisor

Expand All @@ -123,8 +123,8 @@ func CalcGasLimit(parent *types.Block, gasFloor, gasCeil uint64) uint64 {
from parentGasLimit * (2/3) parentGasUsed is.
*/
limit := parent.GasLimit() - decay + contrib
if limit < params.MinGasLimit {
limit = params.MinGasLimit
if limit < minGasLimit {
limit = minGasLimit
}
// If we're outside our allowed gas range, we try to hone towards them
if limit < gasFloor {
Expand Down
2 changes: 1 addition & 1 deletion core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
Difficulty: parent.Difficulty(),
UncleHash: parent.UncleHash(),
}),
GasLimit: CalcGasLimit(parent, parent.GasLimit(), parent.GasLimit()),
GasLimit: CalcGasLimit(parent, parent.GasLimit(), parent.GasLimit(), parent.GasLimit()),
Number: new(big.Int).Add(parent.Number(), common.Big1),
Time: time,
}
Expand Down
2 changes: 1 addition & 1 deletion core/state_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
Difficulty: parent.Difficulty(),
UncleHash: parent.UncleHash(),
}),
GasLimit: CalcGasLimit(parent, parent.GasLimit(), parent.GasLimit()),
GasLimit: CalcGasLimit(parent, parent.GasLimit(), parent.GasLimit(), parent.GasLimit()),
Number: new(big.Int).Add(parent.Number(), common.Big1),
Time: parent.Time() + 10,
UncleHash: types.EmptyUncleHash,
Expand Down
6 changes: 5 additions & 1 deletion eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -833,7 +833,11 @@ func (s *Ethereum) Stop() error {
}

func (s *Ethereum) CalcGasLimit(block *types.Block) uint64 {
return core.CalcGasLimit(block, s.config.Miner.GasFloor, s.config.Miner.GasCeil)
minGasLimit := params.DefaultMinGasLimit
if s != nil && s.config != nil && s.config.Genesis != nil {
minGasLimit = s.config.Genesis.Config.GetMinerMinGasLimit(block.Number(), params.DefaultMinGasLimit)
}
return core.CalcGasLimit(block, minGasLimit, s.config.Miner.GasFloor, s.config.Miner.GasCeil)
}

// (Quorum)
Expand Down
2 changes: 1 addition & 1 deletion eth/ethconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ var Defaults = Config{
TrieTimeout: 60 * time.Minute,
SnapshotCache: 102,
Miner: miner.Config{
GasFloor: params.MinGasLimit,
GasFloor: params.DefaultMinGasLimit,
GasCeil: params.GenesisGasLimit,
GasPrice: big.NewInt(params.GWei),
Recommit: 3 * time.Second,
Expand Down
3 changes: 2 additions & 1 deletion miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -997,11 +997,12 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64)
if parent.Time() >= uint64(timestamp) {
timestamp = int64(parent.Time() + 1)
}
minGasLimit := w.chainConfig.GetMinerMinGasLimit(parent.Number(), params.DefaultMinGasLimit)
num := parent.Number()
header := &types.Header{
ParentHash: parent.Hash(),
Number: num.Add(num, common.Big1),
GasLimit: core.CalcGasLimit(parent, w.config.GasFloor, w.config.GasCeil),
GasLimit: core.CalcGasLimit(parent, minGasLimit, w.config.GasFloor, w.config.GasCeil),
Extra: w.extra,
Time: uint64(timestamp),
}
Expand Down
23 changes: 21 additions & 2 deletions params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,8 +443,9 @@ type Transition struct {
ValidatorContractAddress common.Address `json:"validatorcontractaddress"` // Smart contract address for list of validators
ValidatorSelectionMode string `json:"validatorselectionmode"` // Validator selection mode to switch to
EnhancedPermissioningEnabled bool `json:"enhancedPermissioningEnabled,omitempty"` // aka QIP714Block
PrivacyEnhancementsEnabled bool `json:"privacyEnhancementsEnabled,omitempty"`
PrivacyPrecompileEnalbed bool `json:"privacyPrecompileEnalbed,omitempty"`
PrivacyEnhancementsEnabled bool `json:"privacyEnhancementsEnabled,omitempty"` // privacy enhancements (mandatory party, private state validation)
PrivacyPrecompileEnalbed bool `json:"privacyPrecompileEnabled,omitempty"` // enable marker transactions support
MinerGasLimit uint64 `json:"miner.gaslimit"` // Gas Limit
}

// String implements the fmt.Stringer interface.
Expand Down Expand Up @@ -614,6 +615,21 @@ func (c *ChainConfig) getTransitionValue(num *big.Int, callback func(transition
}
}

// Quorum
//
// GetMinerMinGasLimit returns the miners minGasLimit for the given block number
func (c *ChainConfig) GetMinerMinGasLimit(num *big.Int, defaultValue uint64) uint64 {
minGasLimit := defaultValue
if c != nil && num != nil && len(c.Transitions) > 0 {
for i := 0; i < len(c.Transitions) && c.Transitions[i].Block.Cmp(num) <= 0; i++ {
if c.Transitions[i].MinerGasLimit != 0 {
minGasLimit = c.Transitions[i].MinerGasLimit
}
}
}
return minGasLimit
}

// Quorum
//
// validates the maxCodeSizeConfig data passed in config
Expand Down Expand Up @@ -806,6 +822,9 @@ func isTransitionsConfigCompatible(c1, c2 *ChainConfig, head *big.Int) (error, *
if isSameBlock || c1.Transitions[i].ValidatorSelectionMode != c2.Transitions[i].ValidatorSelectionMode {
return ErrTransitionIncompatible("ValidatorSelectionMode"), head, head
}
if isSameBlock || c1.Transitions[i].MinerGasLimit != c2.Transitions[i].MinerGasLimit {
return ErrTransitionIncompatible("Miner GasLimit"), head, head
}
}

return nil, big.NewInt(0), big.NewInt(0)
Expand Down
10 changes: 5 additions & 5 deletions params/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,10 +330,10 @@ func TestCheckTransitionsData(t *testing.T) {
wantErr error
}
var ibftTransitionsConfig, qbftTransitionsConfig, invalidTransition, invalidBlockOrder []Transition
tranI0 := Transition{big.NewInt(0), IBFT, 30000, 5, 10, 50, common.Address{}, "", false, false, false}
tranQ5 := Transition{big.NewInt(5), QBFT, 30000, 5, 10, 50, common.Address{}, "", false, false, false}
tranI10 := Transition{big.NewInt(10), IBFT, 30000, 5, 10, 50, common.Address{}, "", false, false, false}
tranQ8 := Transition{big.NewInt(8), QBFT, 30000, 5, 10, 50, common.Address{}, "", false, false, false}
tranI0 := Transition{big.NewInt(0), IBFT, 30000, 5, 10, 50, common.Address{}, "", false, false, false, 0}
tranQ5 := Transition{big.NewInt(5), QBFT, 30000, 5, 10, 50, common.Address{}, "", false, false, false, 1}
tranI10 := Transition{big.NewInt(10), IBFT, 30000, 5, 10, 50, common.Address{}, "", false, false, false, 0}
tranQ8 := Transition{big.NewInt(8), QBFT, 30000, 5, 10, 50, common.Address{}, "", false, false, false, 2}

ibftTransitionsConfig = append(ibftTransitionsConfig, tranI0, tranI10)
qbftTransitionsConfig = append(qbftTransitionsConfig, tranQ5, tranQ8)
Expand Down Expand Up @@ -393,7 +393,7 @@ func TestCheckTransitionsData(t *testing.T) {
wantErr: ErrBlockOrder,
},
{
stored: &ChainConfig{Transitions: []Transition{{nil, IBFT, 30000, 5, 10, 50, common.Address{}, "", false, false, false}}},
stored: &ChainConfig{Transitions: []Transition{{nil, IBFT, 30000, 5, 10, 50, common.Address{}, "", false, false, false, 0}}},
wantErr: ErrBlockNumberMissing,
},
{
Expand Down
2 changes: 1 addition & 1 deletion params/protocol_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const (

// modified values for Quorum
GasLimitBoundDivisor uint64 = 4096 // The bound divisor of the gas limit, used in update calculations.
MinGasLimit uint64 = 700000000 // Minimum the gas limit may ever be.
DefaultMinGasLimit uint64 = 700000000 // Minimum the gas limit may ever be.
GenesisGasLimit uint64 = 800000000 // Gas limit of the Genesis block.

MaximumExtraDataSize uint64 = 32 // Maximum size extra data may be after Genesis.
Expand Down
2 changes: 1 addition & 1 deletion params/protocol_params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func TestQuorumParams(t *testing.T) {
}
var testData = map[string]data{
"GasLimitBoundDivisor": {GasLimitBoundDivisor, 4096},
"MinGasLimit": {MinGasLimit, 700000000},
"MinGasLimit": {DefaultMinGasLimit, 700000000},
"GenesisGasLimit": {GenesisGasLimit, 800000000},
"QuorumMaximumExtraDataSize": {QuorumMaximumExtraDataSize, 65},
"QuorumMaxPayloadBufferSize": {QuorumMaxPayloadBufferSize, 128},
Expand Down

0 comments on commit 11bd12f

Please sign in to comment.