revert back to using miner defined gas limit; calc baseFee using EIP1559_GAS_TARGET

This commit is contained in:
Ian Norden
2020-07-06 02:51:25 -05:00
parent 2e959683d2
commit 765f39aa7a
19 changed files with 236 additions and 452 deletions
+3 -4
View File
@@ -156,10 +156,9 @@ var (
utils.EIP1559CLIConfigure,
utils.EIP1559ForkBlockNumber,
utils.EIP1559InitialBaseFee,
utils.EIP1559BaseFeeMaxChangeDenominator,
utils.EIP1559SlackCoefficient,
utils.EIP1559TargetGasUsed,
utils.EIP1559DecayRange,
utils.EIP1559EIP1559BaseFeeMaxChangeDenominator,
utils.EIP1559EIP1559SlackCoefficient,
utils.EIP1559MigrationBlockDuration,
}
rpcFlags = []cli.Flag{
+3 -4
View File
@@ -503,11 +503,10 @@ func (api *RetestethAPI) mineBlock() error {
var gp1559 *core.GasPool
var gasPool *core.GasPool
// See core/gaspool.go for detials on how these gas limit values are calculated
gasPool = core.NewLegacyGasPool(api.chainConfig, header.Number, new(big.Int).SetUint64(header.GasLimit))
if api.chainConfig.IsEIP1559(header.Number) {
gasPool = new(core.GasPool).AddGas(api.chainConfig.EIP1559.MaxGas - header.GasLimit)
gp1559 = new(core.GasPool).AddGas(header.GasLimit)
} else {
gasPool = new(core.GasPool).AddGas(header.GasLimit)
gp1559 = core.NewEIP1559GasPool(api.chainConfig, header.Number, new(big.Int).SetUint64(header.GasLimit))
}
txCount := 0
+3 -4
View File
@@ -267,10 +267,9 @@ var AppHelpFlagGroups = []flagGroup{
utils.EIP1559CLIConfigure,
utils.EIP1559ForkBlockNumber,
utils.EIP1559InitialBaseFee,
utils.EIP1559BaseFeeMaxChangeDenominator,
utils.EIP1559SlackCoefficient,
utils.EIP1559TargetGasUsed,
utils.EIP1559DecayRange,
utils.EIP1559EIP1559BaseFeeMaxChangeDenominator,
utils.EIP1559EIP1559SlackCoefficient,
utils.EIP1559MigrationBlockDuration,
},
},
{
+17 -27
View File
@@ -742,25 +742,20 @@ var (
Usage: "External configuration of EIP1559 ForkBlockNumber",
Value: params.EIP1559ForkBlockNumber,
}
EIP1559BaseFeeMaxChangeDenominator = cli.Uint64Flag{
EIP1559EIP1559BaseFeeMaxChangeDenominator = cli.Uint64Flag{
Name: "eip1559.basefeemaxchangedenominator",
Usage: "External configuration of EIP1559 BaseFeeMaxChangeDenominator",
Value: params.BaseFeeMaxChangeDenominator,
Usage: "External configuration of EIP1559 EIP1559BaseFeeMaxChangeDenominator",
Value: params.EIP1559BaseFeeMaxChangeDenominator,
}
EIP1559TargetGasUsed = cli.Uint64Flag{
Name: "eip1559.targetgasused",
Usage: "External configuration of EIP1559 TargetGasUsed",
Value: params.TargetGasUsed,
}
EIP1559SlackCoefficient = cli.Uint64Flag{
EIP1559EIP1559SlackCoefficient = cli.Uint64Flag{
Name: "eip1559.slackcoefficient",
Usage: "External configuration of EIP1559 SlackCoefficient",
Value: params.SlackCoefficient,
Usage: "External configuration of EIP1559 EIP1559SlackCoefficient",
Value: params.EIP1559SlackCoefficient,
}
EIP1559DecayRange = cli.Uint64Flag{
Name: "eip1559.decayrange",
Usage: "External configuration of EIP1559 DecayRange",
Value: params.EIP1559DecayRange,
EIP1559MigrationBlockDuration = cli.Uint64Flag{
Name: "eip1559.migrationblockduration",
Usage: "External configuration of the number of EIP1559 transition blocks",
Value: params.EIP1559MigrationBlockDuration,
}
)
@@ -1694,22 +1689,17 @@ func setEIP1559Params(ctx *cli.Context, config *eth.Config) {
if ctx.GlobalIsSet(EIP1559InitialBaseFee.Name) {
config.Genesis.Config.EIP1559.InitialBaseFee = ctx.GlobalUint64(EIP1559InitialBaseFee.Name)
}
if ctx.GlobalIsSet(EIP1559TargetGasUsed.Name) {
config.Genesis.Config.EIP1559.TargetGasUsed = ctx.GlobalUint64(EIP1559TargetGasUsed.Name)
if ctx.GlobalIsSet(EIP1559EIP1559SlackCoefficient.Name) {
config.Genesis.Config.EIP1559.EIP1559SlackCoefficient = ctx.GlobalUint64(EIP1559EIP1559SlackCoefficient.Name)
}
if ctx.GlobalIsSet(EIP1559SlackCoefficient.Name) {
config.Genesis.Config.EIP1559.SlackCoefficient = ctx.GlobalUint64(EIP1559SlackCoefficient.Name)
if ctx.GlobalIsSet(EIP1559EIP1559BaseFeeMaxChangeDenominator.Name) {
config.Genesis.Config.EIP1559.EIP1559BaseFeeMaxChangeDenominator = ctx.GlobalUint64(EIP1559EIP1559BaseFeeMaxChangeDenominator.Name)
}
if ctx.GlobalIsSet(EIP1559BaseFeeMaxChangeDenominator.Name) {
config.Genesis.Config.EIP1559.BaseFeeMaxChangeDenominator = ctx.GlobalUint64(EIP1559BaseFeeMaxChangeDenominator.Name)
}
if ctx.GlobalIsSet(EIP1559DecayRange.Name) {
config.Genesis.Config.EIP1559.DecayRange = ctx.GlobalUint64(EIP1559DecayRange.Name)
if ctx.GlobalIsSet(EIP1559MigrationBlockDuration.Name) {
config.Genesis.Config.EIP1559.MigrationBlockDuration = ctx.GlobalUint64(EIP1559MigrationBlockDuration.Name)
}
// Re-calculate the derived config params
config.Genesis.Config.EIP1559.ForkFinalizedBlockNumber = config.Genesis.Config.EIP1559.ForkBlockNumber + config.Genesis.Config.EIP1559.DecayRange
config.Genesis.Config.EIP1559.MaxGas = config.Genesis.Config.EIP1559.SlackCoefficient * config.Genesis.Config.EIP1559.TargetGasUsed
config.Genesis.Config.EIP1559.GasIncrementAmount = (config.Genesis.Config.EIP1559.MaxGas / 2) / config.Genesis.Config.EIP1559.DecayRange
config.Genesis.Config.EIP1559.ForkFinalizedBlockNumber = config.Genesis.Config.EIP1559.ForkBlockNumber + config.Genesis.Config.EIP1559.MigrationBlockDuration
config.Genesis.Config.EIP1559Block = new(big.Int).SetUint64(config.Genesis.Config.EIP1559.ForkBlockNumber)
config.Genesis.Config.EIP1559FinalizedBlock = new(big.Int).SetUint64(config.Genesis.Config.EIP1559.ForkFinalizedBlockNumber)
+18 -23
View File
@@ -264,31 +264,26 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent *
return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, expected)
}
// If EIP1559 is not active we need to verify that the GasLimit field is valid according to the legacy rules
if !chain.Config().IsEIP1559(header.Number) {
// Verify that the gas limit is <= 2^63-1
cap := uint64(0x7fffffffffffffff)
if header.GasLimit > cap {
return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap)
}
// Verify that the gasUsed is <= gasLimit
if header.GasUsed > header.GasLimit {
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
}
// Verify that the "GasLimit" header field is valid
// Verify that the gas limit is <= 2^63-1
max := uint64(0x7fffffffffffffff)
if header.GasLimit > max {
return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, max)
}
// Verify that the gasUsed is <= gasLimit
if header.GasUsed > header.GasLimit {
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
}
// Verify that the gas limit remains within allowed bounds
diff := int64(parent.GasLimit) - int64(header.GasLimit)
if diff < 0 {
diff *= -1
}
limit := parent.GasLimit / params.GasLimitBoundDivisor
// Verify that the gas limit remains within allowed bounds
diff := int64(parent.GasLimit) - int64(header.GasLimit)
if diff < 0 {
diff *= -1
}
limit := parent.GasLimit / params.GasLimitBoundDivisor
if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit {
return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit)
}
// If EIP1559 is active, assert that the GasLimit field is valid according to the EIP1559 rules
} else if err := misc.VerifyEIP1559GasLimit(chain.Config(), header); err != nil {
return err
if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit {
return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit)
}
// Verify that the block number is parent's +1
+123
View File
@@ -0,0 +1,123 @@
// Copyright 2017 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 <http://www.gnu.org/licenses/>.
package misc
import (
"errors"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
)
var (
errInvalidBaseFee = errors.New("invalid BaseFee")
errMissingParentBaseFee = errors.New("parent header is missing BaseFee")
errMissingBaseFee = errors.New("current header is missing BaseFee")
errHaveBaseFee = fmt.Errorf("BaseFee should not be set before block %d", params.EIP1559ForkBlockNumber)
)
// VerifyEIP1559BaseFee verifies that the EIP1559 BaseFee field is valid for the current block height
func VerifyEIP1559BaseFee(config *params.ChainConfig, header, parent *types.Header) error {
if config.IsEIP1559(parent.Number) {
if parent.BaseFee == nil {
return errMissingParentBaseFee
}
}
expectedBaseFee := CalcBaseFee(config, parent)
if header.BaseFee == nil {
if expectedBaseFee != nil {
return errMissingBaseFee
}
return nil
}
if expectedBaseFee == nil {
if header.BaseFee != nil {
return errHaveBaseFee
}
return nil
}
if header.BaseFee.Cmp(expectedBaseFee) != 0 {
return errInvalidBaseFee
}
return nil
}
// CalcBaseFee returns the baseFee for the current block provided the parent header and config parameters
func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
height := new(big.Int).Add(parent.Number, common.Big1)
// If we are before EIP1559 activation, the baseFee is nil
if !config.IsEIP1559(height) {
return nil
}
// If we are at the block of EIP1559 activation then the BaseFee is set to the initial value
if config.EIP1559Block.Cmp(height) == 0 {
return new(big.Int).SetUint64(config.EIP1559.InitialBaseFee)
}
// Otherwise,
// BASEFEE = PARENT_BASEFEE + PARENT_BASEFEE * delta // EIP1559_GAS_TARGET // BASEFEE_MAX_CHANGE_DENOMINATOR
// Where delta = block.gas_used - EIP1559_GAS_TARGET
parentGasTarget := CalcEIP1559GasTarget(config, parent.Number, new(big.Int).SetUint64(parent.GasLimit))
delta := new(big.Int).Sub(new(big.Int).SetUint64(parent.GasUsed), parentGasTarget)
mul := new(big.Int).Mul(parent.BaseFee, delta)
div := new(big.Int).Div(mul, parentGasTarget)
div2 := new(big.Int).Div(div, new(big.Int).SetUint64(config.EIP1559.EIP1559BaseFeeMaxChangeDenominator))
baseFee := new(big.Int).Add(parent.BaseFee, div2)
// A valid BASEFEE is one such that abs(BASEFEE - PARENT_BASEFEE) <= max(1, PARENT_BASEFEE // BASEFEE_MAX_CHANGE_DENOMINATOR)
diff := new(big.Int).Sub(baseFee, parent.BaseFee)
neg := false
if diff.Sign() < 0 {
neg = true
diff.Neg(diff)
}
max := new(big.Int).Div(parent.BaseFee, new(big.Int).SetUint64(config.EIP1559.EIP1559BaseFeeMaxChangeDenominator))
if max.Cmp(common.Big1) < 0 {
max = common.Big1
}
// If derived BaseFee is not valid, restrict it within the bounds
if diff.Cmp(max) > 0 {
if neg {
max.Neg(max)
}
baseFee.Set(new(big.Int).Add(parent.BaseFee, max))
}
return baseFee
}
// CalcEIP1559GasTarget returns the EIP1559GasTarget at the current height and header.GasLimit
// This should only be called at or above the block height of EIP1559 activation and below finalization
func CalcEIP1559GasTarget(chainConfig *params.ChainConfig, height, gasLimit *big.Int) *big.Int {
// After EIP1559 finalization the entire header.GasLimit field instead represents the EIP1559GasTarget
if chainConfig.IsEIP1559Finalized(height) {
return gasLimit
} else if chainConfig.IsEIP1559(height) {
// During transition,
// EIP1559GasTarget = (header.GasLimit/2) + (header.GasLimit/2) * (blockNumber-initBlockNumber) / migrationBlockDuration
// migrationBlockDuration cannot be 0 or IsEIP1559Finalized would be true
halfLim := new(big.Int).Div(gasLimit, big.NewInt(2))
blockDiff := new(big.Int).Sub(height, chainConfig.EIP1559Block)
migrationBlockDuration := new(big.Int).SetUint64(chainConfig.EIP1559.MigrationBlockDuration)
return new(big.Int).Add(halfLim, new(big.Int).Div(new(big.Int).Mul(halfLim, blockDiff), migrationBlockDuration))
}
// Before EIP1559 activation the target is 0
return big.NewInt(0)
}
-81
View File
@@ -17,24 +17,13 @@
package misc
import (
"errors"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
)
var (
errInvalidInitialBaseFee = fmt.Errorf("initial BaseFee must equal %d", params.EIP1559InitialBaseFee)
errInvalidBaseFee = errors.New("invalid BaseFee")
errMissingParentBaseFee = errors.New("parent header is missing BaseFee")
errMissingBaseFee = errors.New("current header is missing BaseFee")
errHaveBaseFee = fmt.Errorf("BaseFee should not be set before block %d", params.EIP1559ForkBlockNumber)
errInvalidEIP1559FinalizedGasLimit = fmt.Errorf("after EIP1559 finalization, GasLimit must equal %d", params.MaxGasEIP1559)
)
// VerifyForkHashes verifies that blocks conforming to network hard-forks do have
// the correct hashes, to avoid clients going off on different chains. This is an
// optional feature.
@@ -52,73 +41,3 @@ func VerifyForkHashes(config *params.ChainConfig, header *types.Header, uncle bo
// All ok, return
return nil
}
// VerifyEIP1559BaseFee verifies that the EIP1559 BaseFee field is valid for the current block height
func VerifyEIP1559BaseFee(config *params.ChainConfig, header, parent *types.Header) error {
// If we are at the EIP1559 fork block the BaseFee needs to be equal to params.EIP1559InitialBaseFee
if config.EIP1559Block != nil && config.EIP1559Block.Cmp(header.Number) == 0 {
if header.BaseFee == nil || header.BaseFee.Cmp(new(big.Int).SetUint64(config.EIP1559.InitialBaseFee)) != 0 {
return errInvalidInitialBaseFee
}
return nil
}
// If we are past the EIP1559 activation block verify the header's BaseFee is valid by deriving
// it from the parent header and validating that they are the same
if config.IsEIP1559(header.Number) {
if parent.BaseFee == nil {
return errMissingParentBaseFee
}
if header.BaseFee == nil {
return errMissingBaseFee
}
delta := new(big.Int).Sub(new(big.Int).SetUint64(parent.GasUsed), new(big.Int).SetUint64(config.EIP1559.TargetGasUsed))
mul := new(big.Int).Mul(parent.BaseFee, delta)
div := new(big.Int).Div(mul, new(big.Int).SetUint64(config.EIP1559.TargetGasUsed))
div2 := new(big.Int).Div(div, new(big.Int).SetUint64(config.EIP1559.BaseFeeMaxChangeDenominator))
expectedBaseFee := new(big.Int).Add(parent.BaseFee, div2)
diff := new(big.Int).Sub(expectedBaseFee, parent.BaseFee)
neg := false
if diff.Sign() < 0 {
neg = true
diff.Neg(diff)
}
max := new(big.Int).Div(parent.BaseFee, new(big.Int).SetUint64(config.EIP1559.BaseFeeMaxChangeDenominator))
if max.Cmp(common.Big1) < 0 {
max = common.Big1
}
if diff.Cmp(max) > 0 {
if neg {
max.Neg(max)
}
expectedBaseFee.Set(new(big.Int).Add(parent.BaseFee, max))
}
if expectedBaseFee.Cmp(header.BaseFee) != 0 {
return errInvalidBaseFee
}
return nil
}
// If we are before the EIP1559 activation block the current and parent BaseFees should be nil
if header.BaseFee != nil || parent.BaseFee != nil {
return errHaveBaseFee
}
return nil
}
// VerifyEIP1559GasLimit verifies that the header.GasLimit field is valid for the current block height
// Only call this after activation has been confirmed (config.IsEIP1559(header.Number) == true)
func VerifyEIP1559GasLimit(config *params.ChainConfig, header *types.Header) error {
// If EIP1559 has been finalized then header.GasLimit should be equal to the MaxGasEIP1559 (entire limit is in EIP1559 pool)
if config.IsEIP1559Finalized(header.Number) {
if header.GasLimit != config.EIP1559.MaxGas {
return errInvalidEIP1559FinalizedGasLimit
}
return nil
}
// Else if we are between activation and finalization, header.GasLimit must be valid based on the decay function
numOfIncrements := new(big.Int).Sub(header.Number, config.EIP1559Block).Uint64()
expectedGasLimit := (config.EIP1559.MaxGas / 2) + (numOfIncrements * config.EIP1559.GasIncrementAmount)
if header.GasLimit != expectedGasLimit {
return fmt.Errorf("invalid GasLimit: have %d, need %d", header.GasLimit, expectedGasLimit)
}
return nil
}
-62
View File
@@ -18,9 +18,7 @@ package core
import (
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
@@ -139,63 +137,3 @@ func CalcGasLimit(parent *types.Block, gasFloor, gasCeil uint64) uint64 {
}
return limit
}
func CalcGasLimitAndBaseFee(config *params.ChainConfig, parent *types.Block, gasFloor, gasCeil uint64) (uint64, *big.Int) {
if !config.IsEIP1559(new(big.Int).Add(parent.Number(), common.Big1)) {
return CalcGasLimit(parent, gasFloor, gasCeil), nil
}
return calcGasLimitAndBaseFee(config, parent)
}
// calcGasLimitAndBaseFee returns the EIP1559GasLimit and the BaseFee
// Start at 50 : 50 and then shift to 0 : 100
// The GasLimit for the legacy pool is (params.MaxGasEIP1559 - EIP1559GasLimit)
func calcGasLimitAndBaseFee(config *params.ChainConfig, parent *types.Block) (uint64, *big.Int) {
height := new(big.Int).Add(parent.Number(), common.Big1)
// If we are at the block of EIP1559 activation then the BaseFee is set to the initial value
// and the GasLimit is split evenly between the two pools
if config.EIP1559Block.Cmp(height) == 0 {
return config.EIP1559.MaxGas / 2, new(big.Int).SetUint64(config.EIP1559.InitialBaseFee)
}
// Otherwise, calculate the BaseFee
// As a default strategy, miners set BASEFEE as follows. Let delta = block.gas_used - TARGET_GASUSED (possibly negative).
// Set BASEFEE = PARENT_BASEFEE + PARENT_BASEFEE * delta // TARGET_GASUSED // BASEFEE_MAX_CHANGE_DENOMINATOR,
delta := new(big.Int).Sub(new(big.Int).SetUint64(parent.GasUsed()), new(big.Int).SetUint64(config.EIP1559.TargetGasUsed))
mul := new(big.Int).Mul(parent.BaseFee(), delta)
div := new(big.Int).Div(mul, new(big.Int).SetUint64(config.EIP1559.TargetGasUsed))
div2 := new(big.Int).Div(div, new(big.Int).SetUint64(config.EIP1559.BaseFeeMaxChangeDenominator))
baseFee := new(big.Int).Add(parent.BaseFee(), div2)
// A valid BASEFEE is one such that abs(BASEFEE - PARENT_BASEFEE) <= max(1, PARENT_BASEFEE // BASEFEE_MAX_CHANGE_DENOMINATOR)
diff := new(big.Int).Sub(baseFee, parent.BaseFee())
neg := false
if diff.Sign() < 0 {
neg = true
diff.Neg(diff)
}
max := new(big.Int).Div(parent.BaseFee(), new(big.Int).SetUint64(config.EIP1559.BaseFeeMaxChangeDenominator))
if max.Cmp(common.Big1) < 0 {
max = common.Big1
}
// If derived BaseFee is not valid, restrict it within the bounds
if diff.Cmp(max) > 0 {
if neg {
max.Neg(max)
}
baseFee.Set(new(big.Int).Add(parent.BaseFee(), max))
}
// If EIP1559 is finalized, our limit for the EIP1559 pool is the entire max limit
if config.IsEIP1559Finalized(new(big.Int).Add(parent.Number(), common.Big1)) {
return params.MaxGasEIP1559, baseFee
}
// Otherwise calculate how much of the MaxGasEIP1559 serves as the limit for the EIP1559 pool
// The GasLimit for the legacy pool is (params.MaxGasEIP1559 - eip1559GasLimit)
numOfIncrements := new(big.Int).Sub(height, config.EIP1559Block).Uint64()
eip1559GasLimit := (config.EIP1559.MaxGas / 2) + (numOfIncrements * config.EIP1559.GasIncrementAmount)
return eip1559GasLimit, baseFee
}
-163
View File
@@ -518,166 +518,3 @@ func testHeaderConcurrentAbortion(t *testing.T, threads int) {
t.Errorf("verification count too large: have %d, want below %d", verified, 2*threads)
}
}
// TestCalcGasLimitAndBaseFee tests that CalcGasLimitAndBaseFee() returns the correct values
func TestCalcGasLimitAndBaseFee(t *testing.T) {
testConditions := []struct {
// Test inputs
config *params.ChainConfig
eip1559Block *big.Int
eip1559FinalizedBlock *big.Int
parentGasLimit uint64
parentGasUsed uint64
parentBaseFee *big.Int
parentBlockNumber *big.Int
// Expected results
gasLimit uint64
baseFee *big.Int
}{
{
// Before activation GasLimit is calculated using the legacy function and BaseFee is nil
params.TestChainConfig,
nil,
nil,
8000000,
8000000,
nil,
big.NewInt(5),
8000000,
nil,
}, {
// At the EIP1559 initialization block the GasLimit is split evenly between the two pools and BaseFee is the initial value
params.EIP1559ChainConfig,
new(big.Int).SetUint64(params.EIP1559ForkBlockNumber),
nil,
8000000,
8000000,
big.NewInt(1100000000),
new(big.Int).SetUint64(params.EIP1559ForkBlockNumber - 1),
params.MaxGasEIP1559 / 2,
new(big.Int).SetUint64(params.EIP1559InitialBaseFee),
},
// After initialization the GasLimit and BaseFee are set according to their functions
// Half way between initialization and finalization we should be at a 25 : 75 legacy : eip1559 split
{
params.EIP1559ChainConfig,
new(big.Int).SetUint64(params.EIP1559ForkBlockNumber),
nil,
8000000,
10000000,
new(big.Int).SetUint64(params.EIP1559InitialBaseFee),
new(big.Int).SetUint64((params.EIP1559ForkBlockNumber + (params.EIP1559ForkFinalizedBlockNumber-params.EIP1559ForkBlockNumber)/2) - 1),
(params.MaxGasEIP1559 * 3) / 4,
new(big.Int).SetUint64(params.EIP1559InitialBaseFee),
},
{
params.EIP1559ChainConfig,
new(big.Int).SetUint64(params.EIP1559ForkBlockNumber),
nil,
8000000,
7000000,
new(big.Int).SetUint64(params.EIP1559InitialBaseFee),
new(big.Int).SetUint64((params.EIP1559ForkBlockNumber + (params.EIP1559ForkFinalizedBlockNumber-params.EIP1559ForkBlockNumber)/2) - 1),
(params.MaxGasEIP1559 * 3) / 4,
new(big.Int).SetUint64(962500000),
},
{
params.EIP1559ChainConfig,
new(big.Int).SetUint64(params.EIP1559ForkBlockNumber),
nil,
8000000,
10000000,
big.NewInt(1100000000),
new(big.Int).SetUint64((params.EIP1559ForkBlockNumber + (params.EIP1559ForkFinalizedBlockNumber-params.EIP1559ForkBlockNumber)/2) - 1),
(params.MaxGasEIP1559 * 3) / 4,
new(big.Int).SetUint64(1100000000),
},
{
params.EIP1559ChainConfig,
new(big.Int).SetUint64(params.EIP1559ForkBlockNumber),
nil,
8000000,
9000000,
big.NewInt(1100000000),
new(big.Int).SetUint64((params.EIP1559ForkBlockNumber + (params.EIP1559ForkFinalizedBlockNumber-params.EIP1559ForkBlockNumber)/2) - 1),
(params.MaxGasEIP1559 * 3) / 4,
new(big.Int).SetUint64(1086250000),
},
// At and beyond EIP1559 finalization the GasLimit (for the EIP1559 pool) is the entire MaxGasEIP1559
{
params.EIP1559FinalizedChainConfig,
new(big.Int).SetUint64(params.EIP1559ForkBlockNumber),
new(big.Int).SetUint64(params.EIP1559ForkFinalizedBlockNumber),
8000000,
9000000,
big.NewInt(1086250000),
new(big.Int).SetUint64(params.EIP1559ForkFinalizedBlockNumber - 1),
params.MaxGasEIP1559,
new(big.Int).SetUint64(1072671875),
},
{
params.EIP1559FinalizedChainConfig,
new(big.Int).SetUint64(params.EIP1559ForkBlockNumber),
new(big.Int).SetUint64(params.EIP1559ForkFinalizedBlockNumber),
8000000,
9000000,
big.NewInt(1072671875),
new(big.Int).SetUint64(params.EIP1559ForkFinalizedBlockNumber + 1),
params.MaxGasEIP1559,
new(big.Int).SetUint64(1059263476),
},
{
params.EIP1559FinalizedChainConfig,
new(big.Int).SetUint64(params.EIP1559ForkBlockNumber),
new(big.Int).SetUint64(params.EIP1559ForkFinalizedBlockNumber),
8000000,
params.TargetGasUsed + 1000,
big.NewInt(1059263476),
new(big.Int).SetUint64(params.EIP1559ForkFinalizedBlockNumber + 10000),
params.MaxGasEIP1559,
new(big.Int).SetUint64(1059276716),
},
{
params.EIP1559FinalizedChainConfig,
new(big.Int).SetUint64(params.EIP1559ForkBlockNumber),
new(big.Int).SetUint64(params.EIP1559ForkFinalizedBlockNumber),
8000000,
params.MaxGasEIP1559,
big.NewInt(1059276716),
new(big.Int).SetUint64(params.EIP1559ForkFinalizedBlockNumber + 10000),
params.MaxGasEIP1559,
new(big.Int).SetUint64(1191686305),
},
{
params.EIP1559FinalizedChainConfig,
new(big.Int).SetUint64(params.EIP1559ForkBlockNumber),
new(big.Int).SetUint64(params.EIP1559ForkFinalizedBlockNumber),
8000000,
0,
big.NewInt(1049238967),
new(big.Int).SetUint64(params.EIP1559ForkFinalizedBlockNumber + 10000),
params.MaxGasEIP1559,
new(big.Int).SetUint64(918084097),
},
}
for i, test := range testConditions {
config := *test.config
config.EIP1559Block = test.eip1559Block
config.EIP1559FinalizedBlock = test.eip1559FinalizedBlock
parentHeader := &types.Header{}
parentHeader.GasLimit = test.parentGasLimit
parentHeader.GasUsed = test.parentGasUsed
parentHeader.BaseFee = test.parentBaseFee
parentHeader.Number = test.parentBlockNumber
parentBlock := types.NewBlockWithHeader(parentHeader)
gasLimit, baseFee := CalcGasLimitAndBaseFee(&config, parentBlock, parentHeader.GasLimit, parentHeader.GasLimit)
if gasLimit != test.gasLimit {
t.Errorf("test %d expected GasLimit %d got %d", i+1, test.gasLimit, gasLimit)
}
if baseFee == nil && test.baseFee != nil {
t.Errorf("test %d expected BaseFee %d got nil", i+1, test.baseFee)
} else if baseFee != nil && baseFee.Cmp(test.baseFee) != 0 {
t.Errorf("test %d expected BaseFee %d got %d", i+1, test.baseFee.Uint64(), baseFee.Uint64())
}
}
}
+5 -12
View File
@@ -59,15 +59,10 @@ func (b *BlockGen) SetCoinbase(addr common.Address) {
panic("coinbase can only be set once")
}
b.header.Coinbase = addr
// If EIP1559 is initialized then header.GasLimit is for the EIP1559 pool
// and the difference between the MaxGasEIP1559 and header.GasLimit is the limit for the legacy pool
// Once EIP1559 is finalized the header.GasLimit is the entire MaxGasEIP1559
// so no gas will be allocated to the legacy pool
// See core/gaspool.go for detials on how these gas limit values are calculated
b.gasPool = NewLegacyGasPool(b.config, b.header.Number, new(big.Int).SetUint64(b.header.GasLimit))
if b.config.IsEIP1559(b.header.Number) {
b.gasPool = new(GasPool).AddGas(b.config.EIP1559.MaxGas - b.header.GasLimit)
b.gasPool1559 = new(GasPool).AddGas(b.header.GasLimit)
} else { // If we are before EIP1559 activation then we use header.GasLimit for the legacy pool
b.gasPool = new(GasPool).AddGas(b.header.GasLimit)
b.gasPool1559 = NewEIP1559GasPool(b.config, b.header.Number, new(big.Int).SetUint64(b.header.GasLimit))
}
}
@@ -258,8 +253,6 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
} else {
time = parent.Time() + 10 // block time is fixed at 10 seconds
}
gasLimit, baseFee := CalcGasLimitAndBaseFee(chain.Config(), parent, parent.GasLimit(), parent.GasLimit())
return &types.Header{
Root: state.IntermediateRoot(chain.Config().IsEIP158(parent.Number())),
ParentHash: parent.Hash(),
@@ -270,8 +263,8 @@ func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.S
Difficulty: parent.Difficulty(),
UncleHash: parent.UncleHash(),
}),
GasLimit: gasLimit,
BaseFee: baseFee,
GasLimit: CalcGasLimit(parent, parent.GasLimit(), parent.GasLimit()),
BaseFee: misc.CalcBaseFee(chain.Config(), parent.Header()),
Number: new(big.Int).Add(parent.Number(), common.Big1),
Time: time,
}
+17
View File
@@ -19,12 +19,29 @@ package core
import (
"fmt"
"math"
"math/big"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/params"
)
// GasPool tracks the amount of gas available during execution of the transactions
// in a block. The zero value is a pool with zero gas available.
type GasPool uint64
// NewLegacyGasPool returns a GasPool filled to the legacy gas limit
func NewLegacyGasPool(chainConfig *params.ChainConfig, height, gasLimit *big.Int) *GasPool {
eip1559GasTarget := misc.CalcEIP1559GasTarget(chainConfig, height, gasLimit)
return new(GasPool).AddGas(gasLimit.Uint64() - eip1559GasTarget.Uint64())
}
// NewEIP1559GasPool returns a GasPool filled to the EIP1559 gas limit
func NewEIP1559GasPool(chainConfig *params.ChainConfig, height, gasLimit *big.Int) *GasPool {
// EIP1559 gas limit is 2x the EIP1559GasTarget
eip1559GasTarget := misc.CalcEIP1559GasTarget(chainConfig, height, gasLimit)
return new(GasPool).AddGas(2 * eip1559GasTarget.Uint64())
}
// AddGas makes gas available for execution.
func (gp *GasPool) AddGas(amount uint64) *GasPool {
if uint64(*gp) > math.MaxUint64-amount {
+6 -10
View File
@@ -17,6 +17,7 @@
package core
import (
"math/big"
"sync/atomic"
"github.com/ethereum/go-ethereum/common"
@@ -51,18 +52,13 @@ func newStatePrefetcher(config *params.ChainConfig, bc *BlockChain, engine conse
func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, cfg vm.Config, interrupt *uint32) {
var (
header = block.Header()
gaspool *GasPool
gp *GasPool
gp1559 *GasPool
)
// If EIP1559 is initialized then header.GasLimit is for the EIP1559 pool
// and the difference between the MaxGasEIP1559 and header.GasLimit is the limit for the legacy pool
// Once EIP1559 is finalized the header.GasLimit is the entire MaxGasEIP1559
// so no gas will be allocated to the legacy pool
// See core/gaspool.go for detials on how these gas limit values are calculated
gp = NewLegacyGasPool(p.config, block.Number(), new(big.Int).SetUint64(block.GasLimit()))
if p.config.IsEIP1559(block.Number()) {
gaspool = new(GasPool).AddGas(p.config.EIP1559.MaxGas - block.GasLimit())
gp1559 = new(GasPool).AddGas(block.GasLimit())
} else { // If we are before EIP1559 activation then we use header.GasLimit for the legacy pool
gaspool = new(GasPool).AddGas(block.GasLimit())
gp1559 = NewEIP1559GasPool(p.config, block.Number(), new(big.Int).SetUint64(block.GasLimit()))
}
// Iterate over and process the individual transactions
byzantium := p.config.IsByzantium(block.Number())
@@ -73,7 +69,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
}
// Block precaching permitted to continue, execute the transaction
statedb.Prepare(tx.Hash(), block.Hash(), i)
if err := precacheTransaction(p.config, p.bc, nil, gaspool, gp1559, statedb, header, tx, cfg); err != nil {
if err := precacheTransaction(p.config, p.bc, nil, gp, gp1559, statedb, header, tx, cfg); err != nil {
return // Ugh, something went horribly wrong, bail out
}
// If we're pre-byzantium, pre-load trie nodes for the intermediate root
+4 -9
View File
@@ -25,6 +25,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"math/big"
)
// StateProcessor is a basic Processor, which takes care of transitioning
@@ -62,17 +63,11 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
gp *GasPool
gp1559 *GasPool
)
// If EIP1559 is initialized then header.GasLimit is for the EIP1559 pool
// and the difference between the MaxGasEIP1559 and header.GasLimit is the limit for the legacy pool
// Once EIP1559 is finalized the header.GasLimit is the entire MaxGasEIP1559
// so no gas will be allocated to the legacy pool
// See core/gaspool.go for detials on how these gas limit values are calculated
gp = NewLegacyGasPool(p.config, block.Number(), new(big.Int).SetUint64(block.GasLimit()))
if p.config.IsEIP1559(block.Number()) {
gp = new(GasPool).AddGas(p.config.EIP1559.MaxGas - block.GasLimit())
gp1559 = new(GasPool).AddGas(block.GasLimit())
} else { // If we are before EIP1559 activation then we use header.GasLimit for the legacy pool
gp = new(GasPool).AddGas(block.GasLimit())
gp1559 = NewEIP1559GasPool(p.config, block.Number(), new(big.Int).SetUint64(block.GasLimit()))
}
// Mutate the block and state according to any hard-fork specs
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
misc.ApplyDAOHardFork(statedb)
+6 -7
View File
@@ -25,6 +25,8 @@ import (
"sync"
"time"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/prque"
"github.com/ethereum/go-ethereum/core/state"
@@ -1215,13 +1217,10 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) {
pool.currentState = statedb
pool.pendingNonces = newTxNoncer(statedb)
if pool.chainconfig.IsEIP1559(newHead.Number) {
pool.currentLegacyMaxGas = pool.chainconfig.EIP1559.MaxGas - newHead.GasLimit
pool.currentEIP1559MaxGas = newHead.GasLimit
} else {
pool.currentLegacyMaxGas = newHead.GasLimit
pool.currentEIP1559MaxGas = 0
}
// eip1559GasTarget will be 0 if below EIP1559 activation and equal to the entire newHead.GasLimit if at or above finalization
eip1559GasTarget := misc.CalcEIP1559GasTarget(pool.chainconfig, newHead.Number, new(big.Int).SetUint64(newHead.GasLimit))
pool.currentLegacyMaxGas = newHead.GasLimit - eip1559GasTarget.Uint64()
pool.currentEIP1559MaxGas = 2 * eip1559GasTarget.Uint64()
// Inject any transactions discarded due to reorgs
log.Debug("Reinjecting stale transactions", "count", len(reinject))
+6 -8
View File
@@ -19,6 +19,7 @@ package light
import (
"context"
"fmt"
"github.com/ethereum/go-ethereum/consensus/misc"
"math/big"
"sync"
"time"
@@ -381,15 +382,12 @@ func (pool *TxPool) validateTx(ctx context.Context, tx *types.Transaction) error
return core.ErrNonceTooLow
}
// Check the transaction doesn't exceed the current
// block limit gas.
// Check the transaction doesn't exceed the current block gas limits
var legacyGasLimit, eip1559GasLimit uint64
if pool.config.IsEIP1559(header.Number) {
legacyGasLimit = pool.config.EIP1559.MaxGas - header.GasLimit
eip1559GasLimit = header.GasLimit
} else {
legacyGasLimit = header.GasLimit
}
// eip1559GasTarget will be 0 if below EIP1559 activation and equal to the entire newHead.GasLimit if at or above finalization
eip1559GasTarget := misc.CalcEIP1559GasTarget(pool.config, header.Number, new(big.Int).SetUint64(header.GasLimit))
legacyGasLimit = header.GasLimit - eip1559GasTarget.Uint64()
eip1559GasLimit = 2 * eip1559GasTarget.Uint64()
if tx.GasPrice() != nil && legacyGasLimit < tx.Gas() {
return core.ErrLegacyGasLimit
}
+12 -15
View File
@@ -749,24 +749,21 @@ func (w *worker) commitTransactions(txs *types.TransactionsByPriceAndNonce, coin
return true
}
// If EIP1559 is initialized then header.GasLimit is for the EIP1559 pool
// and the difference between the MaxGasEIP1559 and header.GasLimit is the limit for the legacy pool
// Once EIP1559 is finalized the header.GasLimit is the entire MaxGasEIP1559
// so no gas will be allocated to the legacy pool
// See core/gaspool.go for detials on how these gas limit values are calculated
var eip1559GasLimit uint64
var legacyGasLimit uint64
if w.current.gasPool == nil {
w.current.gasPool = core.NewLegacyGasPool(w.chainConfig,
w.current.header.Number, new(big.Int).SetUint64(w.current.header.GasLimit))
legacyGasLimit = w.current.gasPool.Gas()
}
if w.chainConfig.IsEIP1559(w.current.header.Number) {
if w.current.gasPool == nil {
legacyGasLimit = w.chainConfig.EIP1559.MaxGas - w.current.header.GasLimit
w.current.gasPool = new(core.GasPool).AddGas(legacyGasLimit)
}
if w.current.gp1559 == nil {
eip1559GasLimit = w.current.header.GasLimit
w.current.gp1559 = new(core.GasPool).AddGas(eip1559GasLimit)
w.current.gp1559 = core.NewEIP1559GasPool(w.chainConfig,
w.current.header.Number, new(big.Int).SetUint64(w.current.header.GasLimit))
eip1559GasLimit = w.current.gp1559.Gas()
}
} else if w.current.gasPool == nil { // If we are before EIP1559 activation then we use header.GasLimit for the legacy pool
legacyGasLimit = w.current.header.GasLimit
w.current.gasPool = new(core.GasPool).AddGas(legacyGasLimit)
}
var coalescedLogs []*types.Log
@@ -922,11 +919,11 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64)
}
num := parent.Number()
gasLimit, baseFee := core.CalcGasLimitAndBaseFee(w.chainConfig, parent, w.config.GasFloor, w.config.GasCeil)
baseFee := misc.CalcBaseFee(w.chainConfig, parent.Header())
header := &types.Header{
ParentHash: parent.Hash(),
Number: num.Add(num, common.Big1),
GasLimit: gasLimit,
GasLimit: core.CalcGasLimit(parent, w.config.GasFloor, w.config.GasCeil),
BaseFee: baseFee,
Extra: w.extra,
Time: uint64(timestamp),
+6 -12
View File
@@ -361,24 +361,18 @@ type EIP1559Config struct {
InitialBaseFee uint64
ForkBlockNumber uint64
ForkFinalizedBlockNumber uint64
DecayRange uint64
GasIncrementAmount uint64
BaseFeeMaxChangeDenominator uint64
TargetGasUsed uint64
MaxGas uint64
SlackCoefficient uint64
MigrationBlockDuration uint64
EIP1559BaseFeeMaxChangeDenominator uint64
EIP1559SlackCoefficient uint64
}
var DefaultEIP1559Config = &EIP1559Config{
InitialBaseFee: EIP1559InitialBaseFee,
ForkBlockNumber: EIP1559ForkBlockNumber,
ForkFinalizedBlockNumber: EIP1559ForkFinalizedBlockNumber,
DecayRange: EIP1559DecayRange,
GasIncrementAmount: EIP1559GasIncrementAmount,
BaseFeeMaxChangeDenominator: BaseFeeMaxChangeDenominator,
TargetGasUsed: TargetGasUsed,
MaxGas: MaxGasEIP1559,
SlackCoefficient: SlackCoefficient,
MigrationBlockDuration: EIP1559MigrationBlockDuration,
EIP1559BaseFeeMaxChangeDenominator: EIP1559BaseFeeMaxChangeDenominator,
EIP1559SlackCoefficient: EIP1559SlackCoefficient,
}
// EthashConfig is the consensus engine configs for proof-of-work based sealing.
+4 -7
View File
@@ -142,13 +142,10 @@ const (
EIP1559InitialBaseFee uint64 = 1000000000 // Wei used as the initial BaseFee
EIP1559ForkBlockNumber uint64 = 110000000 // TBD
EIP1559ForkFinalizedBlockNumber = EIP1559ForkBlockNumber + EIP1559DecayRange
BaseFeeMaxChangeDenominator uint64 = 8
TargetGasUsed uint64 = 10000000
SlackCoefficient uint64 = 2
MaxGasEIP1559 = SlackCoefficient * TargetGasUsed
EIP1559DecayRange uint64 = 1000000
EIP1559GasIncrementAmount = (MaxGasEIP1559 / 2) / EIP1559DecayRange // We need to shift (MaxGasEIP1559 / 2) gas from the legacy pool into the EIP1559 pool over the EIP1559DecayRange
EIP1559MigrationBlockDuration uint64 = 800000
EIP1559ForkFinalizedBlockNumber = EIP1559ForkBlockNumber + EIP1559MigrationBlockDuration
EIP1559BaseFeeMaxChangeDenominator uint64 = 8
EIP1559SlackCoefficient uint64 = 2
)
// Gas discount table for BLS12-381 G1 and G2 multi exponentiation operations
+3 -4
View File
@@ -185,11 +185,10 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
var gp1559 *core.GasPool
var gaspool *core.GasPool
// See core/gaspool.go for detials on how these gas limit values are calculated
gaspool = core.NewLegacyGasPool(config, block.Number(), new(big.Int).SetUint64(block.GasLimit()))
if config.IsEIP1559(block.Number()) {
gaspool = new(core.GasPool).AddGas(config.EIP1559.MaxGas - block.GasLimit())
gp1559 = new(core.GasPool).AddGas(block.GasLimit())
} else {
gaspool = new(core.GasPool).AddGas(block.GasLimit())
gp1559 = core.NewEIP1559GasPool(config, block.Number(), new(big.Int).SetUint64(block.GasLimit()))
}
snapshot := statedb.Snapshot()