diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index 970625bb5..3e9cbeefa 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -265,8 +265,8 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent * return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, expected) } - // If we have not reached the EIP1559 activation block we need to verify that the GasLimit field is valid - if !chain.Config().IsEIP1559Finalized(header.Number) { + // 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 { @@ -287,9 +287,9 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent * if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit { return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit) } - } else if header.GasLimit != 0 { - // If EIP1559 is finalized, GasLimit should be 0 - return errGasLimitSet + // 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 } // Verify that the block number is parent's +1 diff --git a/consensus/misc/forks.go b/consensus/misc/forks.go index a6732ff45..ca2e59ffb 100644 --- a/consensus/misc/forks.go +++ b/consensus/misc/forks.go @@ -27,11 +27,12 @@ import ( ) 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) + 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 @@ -89,3 +90,22 @@ func VerifyEIP1559BaseFee(config *params.ChainConfig, header, parent *types.Head } 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 != params.MaxGasEIP1559 { + 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 := (params.MaxGasEIP1559 / 2) + (numOfIncrements * params.EIP1559GasIncrementAmount) + if header.GasLimit != expectedGasLimit { + return fmt.Errorf("invalid GasLimit: have %d, need %d", header.GasLimit, expectedGasLimit) + } + return nil +} diff --git a/core/block_validator.go b/core/block_validator.go index 58efbaa39..4745e1ab9 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -177,7 +177,7 @@ func calcGasLimitAndBaseFee(config *params.ChainConfig, parent *types.Block) (ui div2 := new(big.Int).Div(div, new(big.Int).SetUint64(params.BaseFeeMaxChangeDenominator)) baseFee := new(big.Int).Add(parent.BaseFee(), div2) - // panic is the BaseFee is not valid + // Panic is the BaseFee is not valid // 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()) if diff.Sign() < 0 { @@ -197,9 +197,8 @@ func calcGasLimitAndBaseFee(config *params.ChainConfig, parent *types.Block) (ui } // Otherwise calculate how much of the MaxGasEIP1559 serves as the limit for the EIP1559 pool - // We need to shift (MaxGasEIP1559 / 2) gas from the legacy pool into the eip1559 pool over the EIP1559DecayRange - gasIncrement := (params.MaxGasEIP1559 / 2) / params.EIP1559DecayRange // 10 gas shifted per block + // The GasLimit for the legacy pool is (params.MaxGasEIP1559 - eip1559GasLimit) numOfIncrements := new(big.Int).Sub(height, config.EIP1559Block).Uint64() - eip1559GasLimit := (params.MaxGasEIP1559 / 2) + (numOfIncrements * gasIncrement) + eip1559GasLimit := (params.MaxGasEIP1559 / 2) + (numOfIncrements * params.EIP1559GasIncrementAmount) return eip1559GasLimit, baseFee }