consensus: Verify gaslimit bounds when accepting blocks (#1619)

* Verify gaslimit bounds when accepting blocks

* fix tests
This commit is contained in:
Wanwiset Peerapatanapokin 2025-10-16 12:16:34 +04:00 committed by GitHub
parent e0c987f45a
commit 6abb4f88da
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 39 additions and 13 deletions

View file

@ -18,6 +18,7 @@ import (
"github.com/XinFinOrg/XDPoSChain/consensus"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
"github.com/XinFinOrg/XDPoSChain/consensus/clique"
"github.com/XinFinOrg/XDPoSChain/consensus/misc"
"github.com/XinFinOrg/XDPoSChain/core/state"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/ethdb"
@ -331,11 +332,18 @@ func (x *XDPoS_v2) Prepare(chain consensus.ChainReader, header *types.Header) er
number := header.Number.Uint64()
parent := chain.GetHeader(header.ParentHash, number-1)
log.Info("Preparing new block!", "Number", number, "Parent Hash", parent.Hash())
if parent == nil {
return consensus.ErrUnknownAncestor
}
// Ensure gas settings are bounded
if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil {
return err
}
if header.GasUsed > header.GasLimit {
return fmt.Errorf("gas used exceeded gaslimit, gas used: %d, gas limit: %d", header.GasUsed, header.GasLimit)
}
log.Info("Preparing new block!", "Number", number, "Parent Hash", parent.Hash())
x.signLock.RLock()
signer := x.signer
x.signLock.RUnlock()
@ -434,6 +442,17 @@ func (x *XDPoS_v2) Finalize(chain consensus.ChainReader, header *types.Header, s
x.saveRewardToFile(header.Hash(), header.Number.Uint64())
}
}
parentHeader := chain.GetHeader(header.ParentHash, header.Number.Uint64()-1)
if parentHeader == nil {
return nil, consensus.ErrUnknownAncestor
}
// Ensure gas settings are bounded
if err := misc.VerifyGaslimit(parentHeader.GasLimit, header.GasLimit); err != nil {
return nil, err
}
if header.GasUsed > header.GasLimit {
return nil, fmt.Errorf("gas used exceeded gaslimit, gas used: %d, gas limit: %d", header.GasUsed, header.GasLimit)
}
// the state remains as is and uncles are dropped
header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))

View file

@ -2,6 +2,7 @@ package engine_v2
import (
"bytes"
"fmt"
"math/big"
"time"
@ -62,7 +63,16 @@ func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Heade
return consensus.ErrUnknownAncestor
}
// Verify this is truly a v2 block first
// Ensure gas limit is consistent with parent
if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil {
return err
}
// Ensure gas used is less than or equal to gas limit
if header.GasUsed > header.GasLimit {
return fmt.Errorf("gas used exceeded gaslimit, gas used: %d, gas limit: %d", header.GasUsed, header.GasLimit)
}
// Verify this is truely a v2 block first
quorumCert, round, _, err := x.getExtraFields(header)
if err != nil {
log.Warn("[verifyHeader] decode extra field error", "err", err)
@ -96,10 +106,6 @@ func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Heade
if header.UncleHash != utils.UncleHash {
return utils.ErrInvalidUncleHash
}
// Verify that the gas limit remains within allowed bounds
if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil {
return err
}
// Verify the header's EIP-1559 attributes.
if err := eip1559.VerifyEip1559Header(chain.Config(), header); err != nil {
return err

View file

@ -876,7 +876,7 @@ func createBlockFromHeader(bc *core.BlockChain, customHeader *types.Header, txs
Coinbase: customHeader.Coinbase,
Difficulty: difficulty,
Number: customHeader.Number,
GasLimit: 1200000000,
GasLimit: params.V2TestsGasLimit,
Time: uint64(time.Now().Unix() - 1000000 + int64(customHeader.Number.Uint64()*10)),
Extra: customHeader.Extra,
Validator: customHeader.Validator,

View file

@ -150,7 +150,7 @@ func TestPrepareFail(t *testing.T) {
notReadyToProposeHeader := &types.Header{
ParentHash: currentBlock.Hash(),
Number: big.NewInt(int64(901)),
GasLimit: params.TargetGasLimit,
GasLimit: params.V2TestsGasLimit,
Time: tstamp,
Coinbase: signer,
}
@ -161,7 +161,7 @@ func TestPrepareFail(t *testing.T) {
notReadyToMine := &types.Header{
ParentHash: currentBlock.Hash(),
Number: big.NewInt(int64(901)),
GasLimit: params.TargetGasLimit,
GasLimit: params.V2TestsGasLimit,
Time: tstamp,
Coinbase: signer,
}
@ -175,7 +175,7 @@ func TestPrepareFail(t *testing.T) {
header901WithoutCoinbase := &types.Header{
ParentHash: currentBlock.Hash(),
Number: big.NewInt(int64(901)),
GasLimit: params.TargetGasLimit,
GasLimit: params.V2TestsGasLimit,
Time: tstamp,
}
@ -196,7 +196,7 @@ func TestPrepareHappyPath(t *testing.T) {
header901 := &types.Header{
ParentHash: currentBlock.Hash(),
Number: big.NewInt(int64(901)),
GasLimit: params.TargetGasLimit,
GasLimit: params.V2TestsGasLimit,
Time: tstamp,
Coinbase: signer,
}
@ -276,7 +276,7 @@ func TestUpdateMultipleMasterNodes(t *testing.T) {
header1800 := &types.Header{
ParentHash: parentBlock.Hash(),
Number: big.NewInt(int64(1800)),
GasLimit: params.TargetGasLimit,
GasLimit: params.V2TestsGasLimit,
Time: tstamp,
Coinbase: voterAddr,
}

View file

@ -49,7 +49,7 @@ func TestHookPenaltyV2Mining(t *testing.T) {
headerMining := &types.Header{
ParentHash: header2100.ParentHash,
Number: header2100.Number,
GasLimit: params.TargetGasLimit,
GasLimit: params.V2TestsGasLimit,
Time: header2100.Time,
Coinbase: acc1Addr,
}

View file

@ -20,6 +20,7 @@ import "math/big"
var (
TargetGasLimit uint64 = XDCGenesisGasLimit // The artificial target
V2TestsGasLimit uint64 = 1200000000 // The gas limit used in the v2 consensus tests
)
const (