From 2eed6c057b1ae3dd03bab5c2f5991b26540a0e7a Mon Sep 17 00:00:00 2001 From: Daniel Liu <139250065@qq.com> Date: Fri, 6 Mar 2026 13:40:32 +0800 Subject: [PATCH] fix(consensus): hardening header verification #33860 (#2071) --- consensus/XDPoS/engines/engine_v1/engine.go | 2 +- .../XDPoS/engines/engine_v2/verifyHeader.go | 2 +- consensus/ethash/consensus.go | 2 +- consensus/misc/eip1559/eip1559.go | 6 +- consensus/misc/eip1559/eip1559_test.go | 81 +++++++++++++++++++ 5 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 consensus/misc/eip1559/eip1559_test.go diff --git a/consensus/XDPoS/engines/engine_v1/engine.go b/consensus/XDPoS/engines/engine_v1/engine.go index c83b4d08d0..cfa11cdf4d 100644 --- a/consensus/XDPoS/engines/engine_v1/engine.go +++ b/consensus/XDPoS/engines/engine_v1/engine.go @@ -235,7 +235,7 @@ func (x *XDPoS_v1) verifyCascadingFields(chain consensus.ChainReader, header *ty return utils.ErrInvalidTimestamp } // Verify the header's EIP-1559 attributes. - if err := eip1559.VerifyEip1559Header(chain.Config(), header); err != nil { + if err := eip1559.VerifyEip1559Header(chain.Config(), parent, header); err != nil { return err } diff --git a/consensus/XDPoS/engines/engine_v2/verifyHeader.go b/consensus/XDPoS/engines/engine_v2/verifyHeader.go index eef4f8933b..1185cfafe8 100644 --- a/consensus/XDPoS/engines/engine_v2/verifyHeader.go +++ b/consensus/XDPoS/engines/engine_v2/verifyHeader.go @@ -110,7 +110,7 @@ func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Heade return utils.ErrInvalidUncleHash } // Verify the header's EIP-1559 attributes. - if err := eip1559.VerifyEip1559Header(chain.Config(), header); err != nil { + if err := eip1559.VerifyEip1559Header(chain.Config(), parent, header); err != nil { return err } if header.Difficulty.Cmp(big.NewInt(1)) != 0 { diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index 6517df302a..889c9a2abd 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -202,7 +202,7 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent * return err } // Verify the header's EIP-1559 attributes. - if err := eip1559.VerifyEip1559Header(chain.Config(), header); err != nil { + if err := eip1559.VerifyEip1559Header(chain.Config(), parent, header); err != nil { return err } diff --git a/consensus/misc/eip1559/eip1559.go b/consensus/misc/eip1559/eip1559.go index 219122ce83..b3f638b2b9 100644 --- a/consensus/misc/eip1559/eip1559.go +++ b/consensus/misc/eip1559/eip1559.go @@ -29,7 +29,7 @@ import ( // VerifyEip1559Header verifies some header attributes which were changed in EIP-1559, // - gas limit check // - basefee check -func VerifyEip1559Header(config *params.ChainConfig, header *types.Header) error { +func VerifyEip1559Header(config *params.ChainConfig, parent, header *types.Header) error { if !config.IsEIP1559(header.Number) { if header.BaseFee != nil { return fmt.Errorf("invalid baseFee: have %s, want ", @@ -42,6 +42,10 @@ func VerifyEip1559Header(config *params.ChainConfig, header *types.Header) error if header.BaseFee == nil { return errors.New("header is missing baseFee") } + // Verify the parent header is not malformed + if parent != nil && config.IsEIP1559(parent.Number) && parent.BaseFee == nil { + return errors.New("parent header is missing baseFee") + } // Verify the baseFee is correct based on the current header. expectedBaseFee := CalcBaseFee(config, header) diff --git a/consensus/misc/eip1559/eip1559_test.go b/consensus/misc/eip1559/eip1559_test.go new file mode 100644 index 0000000000..102511bb30 --- /dev/null +++ b/consensus/misc/eip1559/eip1559_test.go @@ -0,0 +1,81 @@ +// Copyright 2021 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 . + +package eip1559 + +import ( + "math/big" + "testing" + + "github.com/XinFinOrg/XDPoSChain/common" + "github.com/XinFinOrg/XDPoSChain/core/types" + "github.com/XinFinOrg/XDPoSChain/params" +) + +func testConfigEip1559() *params.ChainConfig { + config := *params.TestChainConfig + config.Eip1559Block = big.NewInt(1) + return &config +} + +func TestVerifyEip1559HeaderParentBaseFee(t *testing.T) { + config := testConfigEip1559() + + for _, tc := range []struct { + name string + parent *types.Header + headerNum int64 + wantOk bool + }{ + { + name: "eip1559 parent missing basefee", + parent: &types.Header{ + Number: big.NewInt(1), + }, + headerNum: 2, + wantOk: false, + }, + { + name: "eip1559 parent with basefee", + parent: &types.Header{ + Number: big.NewInt(1), + BaseFee: new(big.Int).Set(common.BaseFee), + }, + headerNum: 2, + wantOk: true, + }, + { + name: "pre-eip1559 parent ignores basefee", + parent: &types.Header{ + Number: big.NewInt(0), + }, + headerNum: 1, + wantOk: true, + }, + } { + header := &types.Header{ + Number: big.NewInt(tc.headerNum), + BaseFee: new(big.Int).Set(common.BaseFee), + } + err := VerifyEip1559Header(config, tc.parent, header) + if tc.wantOk && err != nil { + t.Fatalf("%s: expected no error, got %v", tc.name, err) + } + if !tc.wantOk && err == nil { + t.Fatalf("%s: expected error, got nil", tc.name) + } + } +}