diff --git a/consensus/qbft/backend/engine_test.go b/consensus/qbft/backend/engine_test.go index 38c0bdccdf..1a71163372 100644 --- a/consensus/qbft/backend/engine_test.go +++ b/consensus/qbft/backend/engine_test.go @@ -32,6 +32,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/misc/eip1559" "github.com/ethereum/go-ethereum/consensus/qbft" qbftcommon "github.com/ethereum/go-ethereum/consensus/qbft/common" qbftcore "github.com/ethereum/go-ethereum/consensus/qbft/core" @@ -44,6 +45,7 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth/fetcher" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/triedb" @@ -179,19 +181,22 @@ func copyConfig(config *qbft.Config) *qbft.Config { return &cpy } -func makeHeader(parent *types.Block, config *qbft.Config) *types.Header { +// makeHeader create header executing no txs +func makeHeader(chainConfig *params.ChainConfig, engineConfig *qbft.Config, parent *types.Block) *types.Header { blockNumber := parent.Number().Add(parent.Number(), common.Big1) header := &types.Header{ ParentHash: parent.Hash(), Number: blockNumber, - GasLimit: core.CalcGasLimit(parent.GasLimit(), parent.GasLimit()), - GasUsed: 0, - Time: parent.Time() + config.GetConfig(blockNumber).BlockPeriod, + GasLimit: parent.GasLimit(), + GasUsed: 0, // empty tx + Time: parent.Time() + engineConfig.GetConfig(blockNumber).BlockPeriod, Difficulty: types.QBFTDefaultDifficulty, + BaseFee: eip1559.CalcBaseFee(chainConfig, parent.Header()), } return header } +// makeBlock create block executing no txs func makeBlock(chain *core.BlockChain, engine *Backend, parent *types.Block) *types.Block { block := makeBlockWithoutSeal(chain, engine, parent) state, _ := chain.State() @@ -202,8 +207,9 @@ func makeBlock(chain *core.BlockChain, engine *Backend, parent *types.Block) *ty return blk } +// makeBlock create block executing no txs without seal func makeBlockWithoutSeal(chain *core.BlockChain, engine *Backend, parent *types.Block) *types.Block { - header := makeHeader(parent, engine.config) + header := makeHeader(chain.Config(), engine.config, parent) engine.Prepare(chain, header) block := types.NewBlock(header, nil, nil, nil, trie.NewStackTrie(nil)) return block @@ -212,7 +218,7 @@ func makeBlockWithoutSeal(chain *core.BlockChain, engine *Backend, parent *types func TestQBFTPrepare(t *testing.T) { chain, engine, _ := newBlockChain(1) defer engine.Stop() - header := makeHeader(chain.Genesis(), engine.config) + header := makeHeader(chain.Config(), engine.config, chain.Genesis()) err := engine.Prepare(chain, header) if err != nil { t.Errorf("error mismatch: have %v, want nil", err) diff --git a/consensus/qbft/engine/engine.go b/consensus/qbft/engine/engine.go index 11951ccdf5..129cfb7dd9 100644 --- a/consensus/qbft/engine/engine.go +++ b/consensus/qbft/engine/engine.go @@ -14,6 +14,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/misc" + "github.com/ethereum/go-ethereum/consensus/misc/eip1559" "github.com/ethereum/go-ethereum/consensus/qbft" qbftcommon "github.com/ethereum/go-ethereum/consensus/qbft/common" "github.com/ethereum/go-ethereum/consensus/qbft/core" @@ -21,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/trie" "github.com/holiman/uint256" @@ -181,7 +184,31 @@ func (e *Engine) verifyHeader(chain consensus.ChainHeaderReader, header *types.H if header.Difficulty == nil || header.Difficulty.Cmp(types.QBFTDefaultDifficulty) != 0 { return qbftcommon.ErrInvalidDifficulty } + // Verify that the gas limit is <= 2^63-1 + if header.GasLimit > params.MaxGasLimit { + return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, params.MaxGasLimit) + } + if chain.Config().IsShanghai(header.Number, header.Time) { + return errors.New("wbft does not support shanghai fork") + } + // Verify the non-existence of withdrawalsHash. + if header.WithdrawalsHash != nil { + return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash) + } + if chain.Config().IsCancun(header.Number, header.Time) { + return errors.New("wbft does not support cancun fork") + } + // Verify the non-existence of cancun-specific header fields + switch { + case header.ExcessBlobGas != nil: + return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas) + case header.BlobGasUsed != nil: + return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed) + case header.ParentBeaconRoot != nil: + return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", header.ParentBeaconRoot) + } + // All basic checks passed, verify cascading fields return e.verifyCascadingFields(chain, header, validators, prevValidators, parents, checkSeals) } @@ -215,6 +242,22 @@ func (e *Engine) verifyCascadingFields(chain consensus.ChainHeaderReader, header if parent.Time+e.cfg.GetConfig(header.Number).BlockPeriod > header.Time { return qbftcommon.ErrInvalidTimestamp } + // Verify that the gasUsed is <= gasLimit + if header.GasUsed > header.GasLimit { + return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) + } + if !chain.Config().IsLondon(header.Number) { + // Verify BaseFee not present before EIP-1559 fork. + if header.BaseFee != nil { + return fmt.Errorf("invalid baseFee before fork: have %d, want ", header.BaseFee) + } + if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil { + return err + } + } else if err := eip1559.VerifyEIP1559Header(chain.Config(), parent, header); err != nil { + // Verify the header's EIP-1559 attributes. + return err + } // Verify signer if err := e.verifySigner(chain, header, parents, validators); err != nil {