Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement EIP7783: Controlled Gas limit increase #30570

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions accounts/abi/bind/bind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1818,7 +1818,7 @@ var bindTests = []struct {
var (
key, _ = crypto.GenerateKey()
user, _ = bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil)
sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.EIP7783InitialGasLimit)
)
defer sim.Close()

Expand Down Expand Up @@ -1889,7 +1889,7 @@ var bindTests = []struct {
var (
key, _ = crypto.GenerateKey()
user, _ = bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil)
sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.EIP7783InitialGasLimit)
)
defer sim.Close()

Expand Down Expand Up @@ -1942,7 +1942,7 @@ var bindTests = []struct {
var (
key, _ = crypto.GenerateKey()
user, _ = bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil)
sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.EIP7783InitialGasLimit)
)
defer sim.Close()

Expand Down Expand Up @@ -1991,7 +1991,7 @@ var bindTests = []struct {
var (
key, _ = crypto.GenerateKey()
user, _ = bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil)
sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.EIP7783InitialGasLimit)
)
defer sim.Close()

Expand Down Expand Up @@ -2032,7 +2032,7 @@ var bindTests = []struct {
var (
key, _ = crypto.GenerateKey()
user, _ = bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337))
sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.GasCeil)
sim = backends.NewSimulatedBackend(types.GenesisAlloc{user.From: {Balance: big.NewInt(1000000000000000000)}}, ethconfig.Defaults.Miner.EIP7783InitialGasLimit)
)
_, tx, _, err := DeployRangeKeyword(user, sim)
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ var (
utils.MaxPendingPeersFlag,
utils.MiningEnabledFlag, // deprecated
utils.MinerGasLimitFlag,
utils.MinerEIP7783BlockNumStartFlag,
utils.MinerEIP7783GasLimitCapFlag,
utils.MinerEIP7783IncreaseRateFlag,
utils.MinerEIP7783InitialGasLimitFlag,
utils.MinerGasPriceFlag,
utils.MinerEtherbaseFlag, // deprecated
utils.MinerExtraDataFlag,
Expand Down
41 changes: 39 additions & 2 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,30 @@ var (
MinerGasLimitFlag = &cli.Uint64Flag{
Name: "miner.gaslimit",
Usage: "Target gas ceiling for mined blocks",
Value: ethconfig.Defaults.Miner.GasCeil,
Category: flags.MinerCategory,
}
MinerEIP7783BlockNumStartFlag = &flags.BigFlag{
Name: "miner.eip7783.blocknumstart",
Usage: "The block number to start using EIP-7783 gas limit calculation",
Value: ethconfig.Defaults.Miner.EIP7783BlockNumStart,
Category: flags.MinerCategory,
}
MinerEIP7783InitialGasLimitFlag = &cli.Uint64Flag{
Name: "miner.eip7783.initialgaslimit",
Usage: "The initial gas limit to use before EIP-7783 calculation",
Value: ethconfig.Defaults.Miner.EIP7783InitialGasLimit,
Category: flags.MinerCategory,
}
MinerEIP7783IncreaseRateFlag = &cli.Uint64Flag{
Name: "miner.eip7783.increaserate",
Usage: "The rate of gas limit increase per block",
Value: ethconfig.Defaults.Miner.Eip7783IncreaseRate,
Category: flags.MinerCategory,
}
MinerEIP7783GasLimitCapFlag = &cli.Uint64Flag{
Name: "miner.eip7783.gaslimitcap",
Usage: "The maximum gas limit to use after EIP-7783 calculation",
Value: ethconfig.Defaults.Miner.EIP7783GasLimitCap,
Category: flags.MinerCategory,
}
MinerGasPriceFlag = &flags.BigFlag{
Expand Down Expand Up @@ -1553,8 +1576,22 @@ func setMiner(ctx *cli.Context, cfg *miner.Config) {
cfg.ExtraData = []byte(ctx.String(MinerExtraDataFlag.Name))
}
if ctx.IsSet(MinerGasLimitFlag.Name) {
cfg.GasCeil = ctx.Uint64(MinerGasLimitFlag.Name)
cfg.GasCeil = new(uint64)
*cfg.GasCeil = ctx.Uint64(MinerGasLimitFlag.Name)
}
if ctx.IsSet(MinerEIP7783BlockNumStartFlag.Name) {
cfg.EIP7783BlockNumStart = flags.GlobalBig(ctx, MinerEIP7783BlockNumStartFlag.Name)
}
if ctx.IsSet(MinerEIP7783GasLimitCapFlag.Name) {
cfg.EIP7783GasLimitCap = ctx.Uint64(MinerEIP7783GasLimitCapFlag.Name)
}
if ctx.IsSet(MinerEIP7783IncreaseRateFlag.Name) {
cfg.Eip7783IncreaseRate = ctx.Uint64(MinerEIP7783IncreaseRateFlag.Name)
}
if ctx.IsSet(MinerEIP7783InitialGasLimitFlag.Name) {
cfg.EIP7783InitialGasLimit = ctx.Uint64(MinerEIP7783InitialGasLimitFlag.Name)
}

if ctx.IsSet(MinerGasPriceFlag.Name) {
cfg.GasPrice = flags.GlobalBig(ctx, MinerGasPriceFlag.Name)
}
Expand Down
21 changes: 21 additions & 0 deletions consensus/misc/eip7783/eip7783.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package eip7783

import "math/big"

/*
Implementation of EIP-7783:

def compute_gas_limit(blockNum: int, blockNumStart: int, initialGasLimit: int, r: int, gasLimitCap: int) -> int:

if blockNum < blockNumStart:
return initialGasLimit
else:
return min(gasLimitCap, initialGasLimit + r * (blockNum - blockNumStart))
*/
func CalcGasLimitEIP7783(blockNum, startBlockNum *big.Int, initialGasLimit, gasIncreaseRate, gasLimitCap uint64) uint64 {
if blockNum.Cmp(startBlockNum) < 0 {
return initialGasLimit
} else {
return min(gasLimitCap, initialGasLimit+gasIncreaseRate*(blockNum.Uint64()-startBlockNum.Uint64()))
}
}
24 changes: 24 additions & 0 deletions consensus/misc/eip7783/eip7783_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package eip7783

import (
"math/big"
"testing"
)

func TestCalcGasLimitEIP7783Test(t *testing.T) {
// Do multiple tests here
tests := []struct {
blockNum, startBlockNum *big.Int
initialGasLimit, gasIncreaseRate, gasLimitCap, expectedGasLimit uint64
}{
{big.NewInt(100), big.NewInt(50), 100000, 10, 200000, 100500},
{big.NewInt(100), big.NewInt(100), 100000, 10, 200000, 100000},
{big.NewInt(99), big.NewInt(100), 100000, 10, 200000, 100000},
}

for i, test := range tests {
if have, want := CalcGasLimitEIP7783(test.blockNum, test.startBlockNum, test.initialGasLimit, test.gasIncreaseRate, test.gasLimitCap), test.expectedGasLimit; have != want {
t.Errorf("test %d: have %d want %d, ", i, have, want)
}
}
}
2 changes: 2 additions & 0 deletions eth/catalyst/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,8 @@ func startEthService(t *testing.T, genesis *core.Genesis, blocks []*types.Block)
mcfg := miner.DefaultConfig
mcfg.PendingFeeRecipient = testAddr
ethcfg := &ethconfig.Config{Genesis: genesis, SyncMode: downloader.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256, Miner: mcfg}
ethcfg.Miner.GasCeil = new(uint64)
*ethcfg.Miner.GasCeil = 30_000_000
ethservice, err := eth.New(n, ethcfg)
if err != nil {
t.Fatal("can't create eth service:", err)
Expand Down
5 changes: 4 additions & 1 deletion eth/catalyst/simulated_beacon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ func startSimulatedBeaconEthService(t *testing.T, genesis *core.Genesis, period
t.Fatal("can't create node:", err)
}

ethcfg := &ethconfig.Config{Genesis: genesis, SyncMode: downloader.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256, Miner: miner.DefaultConfig}
m := miner.DefaultConfig
m.GasCeil = new(uint64)
// *m.GasCeil = 30_000_000
ethcfg := &ethconfig.Config{Genesis: genesis, SyncMode: downloader.FullSync, TrieTimeout: time.Minute, TrieDirtyCache: 256, TrieCleanCache: 256, Miner: m}
ethservice, err := eth.New(n, ethcfg)
if err != nil {
t.Fatal("can't create eth service:", err)
Expand Down
3 changes: 2 additions & 1 deletion ethclient/ethclient_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
Expand Down Expand Up @@ -219,7 +220,7 @@ func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
t.Fatalf("can't create new node: %v", err)
}
// Create Ethereum Service
config := &ethconfig.Config{Genesis: genesis, RPCGasCap: 1000000}
config := &ethconfig.Config{Genesis: genesis, RPCGasCap: 1000000, Miner: miner.Config{GasCeil: new(uint64)}}
ethservice, err := eth.New(n, config)
if err != nil {
t.Fatalf("can't create new ethereum service: %v", err)
Expand Down
2 changes: 1 addition & 1 deletion ethclient/simulated/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func NewBackend(alloc types.GenesisAlloc, options ...func(nodeConf *node.Config,
ethConf := ethconfig.Defaults
ethConf.Genesis = &core.Genesis{
Config: params.AllDevChainProtocolChanges,
GasLimit: ethconfig.Defaults.Miner.GasCeil,
GasLimit: ethconfig.Defaults.Miner.EIP7783InitialGasLimit,
Alloc: alloc,
}
ethConf.SyncMode = downloader.FullSync
Expand Down
3 changes: 2 additions & 1 deletion ethclient/simulated/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ import (
func WithBlockGasLimit(gaslimit uint64) func(nodeConf *node.Config, ethConf *ethconfig.Config) {
return func(nodeConf *node.Config, ethConf *ethconfig.Config) {
ethConf.Genesis.GasLimit = gaslimit
ethConf.Miner.GasCeil = gaslimit
ethConf.Miner.GasCeil = new(uint64)
*ethConf.Miner.GasCeil = gaslimit
}
}

Expand Down
19 changes: 15 additions & 4 deletions miner/miner.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package miner

import (
"fmt"
"math"
"math/big"
"sync"
"time"
Expand All @@ -45,15 +46,25 @@ type Config struct {
Etherbase common.Address `toml:"-"` // Deprecated
PendingFeeRecipient common.Address `toml:"-"` // Address for pending block rewards.
ExtraData hexutil.Bytes `toml:",omitempty"` // Block extra data set by the miner
GasCeil uint64 // Target gas ceiling for mined blocks.
GasCeil *uint64 // Target gas ceiling for mined blocks.
GasPrice *big.Int // Minimum gas price for mining a transaction
Recommit time.Duration // The time interval for miner to re-create mining work.

// EIP-7783 parameters
EIP7783BlockNumStart *big.Int // The block number to start using EIP-7783 gas limit calculation
EIP7783InitialGasLimit uint64 // The initial gas limit to use before EIP-7783 calculation
Eip7783IncreaseRate uint64 // The rate of gas limit increase per block
EIP7783GasLimitCap uint64 // The maximum gas limit to use after EIP-7783 calculation
}

// DefaultConfig contains default settings for miner.
var DefaultConfig = Config{
GasCeil: 30_000_000,
GasPrice: big.NewInt(params.GWei / 1000),
//GasCeil: 30_000_000,
GasPrice: big.NewInt(params.GWei / 1000),
EIP7783InitialGasLimit: 30_000_000,
Eip7783IncreaseRate: 6,
EIP7783GasLimitCap: 60_000_000,
EIP7783BlockNumStart: big.NewInt(math.MaxInt64),

// The default recommit time is chosen as two seconds since
// consensus-layer usually will wait a half slot of time(6s)
Expand Down Expand Up @@ -113,7 +124,7 @@ func (miner *Miner) SetExtra(extra []byte) error {
// For pre-1559 blocks, it sets the ceiling.
func (miner *Miner) SetGasCeil(ceil uint64) {
miner.confMu.Lock()
miner.config.GasCeil = ceil
miner.config.GasCeil = &ceil
miner.confMu.Unlock()
}

Expand Down
1 change: 1 addition & 0 deletions miner/miner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ func createMiner(t *testing.T) *Miner {

// Create Miner
backend := NewMockBackend(bc, txpool)
config.GasCeil = new(uint64)
miner := New(backend, config, engine)
return miner
}
4 changes: 2 additions & 2 deletions miner/payload_building_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ var (

testUserKey, _ = crypto.GenerateKey()
testUserAddress = crypto.PubkeyToAddress(testUserKey.PublicKey)

genesisGasLimit = params.GenesisGasLimit
// Test transactions
pendingTxs []*types.Transaction
newTxs []*types.Transaction

testConfig = Config{
PendingFeeRecipient: testBankAddress,
Recommit: time.Second,
GasCeil: params.GenesisGasLimit,
GasCeil: &genesisGasLimit,
}
)

Expand Down
18 changes: 16 additions & 2 deletions miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/consensus/misc/eip7783"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/stateless"
Expand Down Expand Up @@ -171,11 +172,24 @@ func (miner *Miner) prepareWork(genParams *generateParams, witness bool) (*envir
}
timestamp = parent.Time + 1
}
useEip7783 := miner.config.GasCeil == nil
var gasCeil uint64

if useEip7783 {
parentNumber := parent.Number
if parentNumber == nil {
parentNumber = common.Big0
}
gasCeil = eip7783.CalcGasLimitEIP7783(new(big.Int).Add(parentNumber, common.Big1), miner.config.EIP7783BlockNumStart, miner.config.EIP7783InitialGasLimit, miner.config.Eip7783IncreaseRate, miner.config.EIP7783GasLimitCap)
} else {
gasCeil = *miner.config.GasCeil
}

// Construct the sealing block header.
header := &types.Header{
ParentHash: parent.Hash(),
Number: new(big.Int).Add(parent.Number, common.Big1),
GasLimit: core.CalcGasLimit(parent.GasLimit, miner.config.GasCeil),
GasLimit: core.CalcGasLimit(parent.GasLimit, gasCeil),
Time: timestamp,
Coinbase: genParams.coinbase,
}
Expand All @@ -192,7 +206,7 @@ func (miner *Miner) prepareWork(genParams *generateParams, witness bool) (*envir
header.BaseFee = eip1559.CalcBaseFee(miner.chainConfig, parent)
if !miner.chainConfig.IsLondon(parent.Number) {
parentGasLimit := parent.GasLimit * miner.chainConfig.ElasticityMultiplier()
header.GasLimit = core.CalcGasLimit(parentGasLimit, miner.config.GasCeil)
header.GasLimit = core.CalcGasLimit(parentGasLimit, gasCeil)
}
}
// Run the consensus preparation with the default or customized consensus engine.
Expand Down