parlia: reject header with non-nil WithdrawalsHash(#1884)

* parlia: reject header with `WithdrawalsHash` before shanghai fork

* log: output chainconfig when start up

* eth: fix TestOptionMaxPeersPerIP failure of goroutine order
This commit is contained in:
Nathan 2023-09-21 12:02:59 +08:00 committed by GitHub
parent 41f0667ce1
commit 52e2cb86a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 78 additions and 70 deletions

@ -262,7 +262,7 @@ func TestT8n(t *testing.T) {
output: t8nOutput{alloc: true, result: true},
expOut: "exp.json",
},
// TODO: Cancun not ready
// TODO(Nathan): Cancun not ready
/*
{ // Cancun tests
base: "./testdata/28",

@ -30,7 +30,7 @@ import (
)
const (
ipcAPIs = "admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 rpc:1.0 txpool:1.0 web3:1.0"
ipcAPIs = "admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 parlia:1.0 rpc:1.0 txpool:1.0 web3:1.0"
httpAPIs = "eth:1.0 net:1.0 rpc:1.0 web3:1.0"
)

@ -542,12 +542,13 @@ var (
Name: "miner.delayleftover",
Usage: "Time reserved to finalize a block",
Value: ethconfig.Defaults.Miner.DelayLeftOver,
Category: flags.MinerCategory,
}
MinerNewPayloadTimeout = &cli.DurationFlag{
Name: "miner.newpayload-timeout",
Usage: "Specify the maximum time allowance for creating a new payload",
Value: ethconfig.Defaults.Miner.NewPayloadTimeout,
Category: flags.MinerCategory,
// Category: flags.MinerCategory,
}
// Account settings

@ -29,6 +29,7 @@ import (
cmath "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/forkid"
"github.com/ethereum/go-ethereum/core/state"
@ -566,6 +567,24 @@ func (p *Parlia) verifyHeader(chain consensus.ChainHeaderReader, header *types.H
return err
}
// Verify existence / non-existence of withdrawalsHash.
if header.WithdrawalsHash != nil {
return fmt.Errorf("invalid withdrawalsHash: have %x, expected nil", header.WithdrawalsHash)
}
// Verify the existence / non-existence of excessBlobGas
cancun := chain.Config().IsCancun(header.Number, header.Time)
if !cancun && header.ExcessBlobGas != nil {
return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas)
}
if !cancun && header.BlobGasUsed != nil {
return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed)
}
if cancun {
if err := eip4844.VerifyEIP4844Header(parent, header); err != nil {
return err
}
}
// All basic checks passed, verify cascading fields
return p.verifyCascadingFields(chain, header, parents)
}
@ -1924,7 +1943,7 @@ func applyMessage(
chainConfig *params.ChainConfig,
chainContext core.ChainContext,
) (uint64, error) {
// TODO: state.Prepare should be called here, now accessList related EIP not affect systemtxs
// TODO(Nathan): state.Prepare should be called here, now accessList related EIP not affect systemtxs
// EIP1153 may cause a critical issue in the future
// Create a new context to be used in the EVM environment
context := core.NewEVMBlockContext(header, chainContext, nil)

@ -24,7 +24,6 @@ import (
"math/big"
"runtime"
"sort"
"strings"
"sync"
"sync/atomic"
"time"
@ -291,6 +290,9 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok {
return nil, genesisErr
}
log.Info("Initialised chain configuration", "config", chainConfig)
// Description of chainConfig is empty now
/*
log.Info("")
log.Info(strings.Repeat("-", 153))
for _, line := range strings.Split(chainConfig.Description(), "\n") {
@ -298,6 +300,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
}
log.Info(strings.Repeat("-", 153))
log.Info("")
*/
bc := &BlockChain{
chainConfig: chainConfig,

@ -66,8 +66,8 @@ type Genesis struct {
GasUsed uint64 `json:"gasUsed"`
ParentHash common.Hash `json:"parentHash"`
BaseFee *big.Int `json:"baseFeePerGas"` // EIP-1559
ExcessBlobGas *uint64 `json:"excessBlobGas,omitempty" toml:",omitempty"` // EIP-4844, TODO: remove tag `omitempty` after cancun fork
BlobGasUsed *uint64 `json:"blobGasUsed,omitempty" toml:",omitempty"` // EIP-4844, TODO: remove tag `omitempty` after cancun fork
ExcessBlobGas *uint64 `json:"excessBlobGas,omitempty" toml:",omitempty"` // EIP-4844, TODO(Nathan): remove tag `omitempty` after cancun fork
BlobGasUsed *uint64 `json:"blobGasUsed,omitempty" toml:",omitempty"` // EIP-4844, TODO(Nathan): remove tag `omitempty` after cancun fork
}
func ReadGenesis(db ethdb.Database) (*Genesis, error) {

@ -366,9 +366,7 @@ func (dl *diskLayer) generateRange(ctx *generatorContext, trieId *trie.ID, prefi
return false, nil, err
}
if nodes != nil {
// TODO(Nathan): why block is zero?
block := uint64(0)
tdb.Update(root, types.EmptyRootHash, block, trienode.NewWithNodeSet(nodes), nil)
tdb.Update(root, types.EmptyRootHash, 0, trienode.NewWithNodeSet(nodes), nil)
tdb.Commit(root, false)
}
resolver = func(owner common.Hash, path []byte, hash common.Hash) []byte {

@ -13,7 +13,6 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/params"
)
var votesManagerCounter = metrics.NewRegisteredCounter("votesManager/local", nil)
@ -29,7 +28,6 @@ type VoteManager struct {
eth Backend
chain *core.BlockChain
chainconfig *params.ChainConfig
chainHeadCh chan core.ChainHeadEvent
chainHeadSub event.Subscription
@ -45,12 +43,10 @@ type VoteManager struct {
engine consensus.PoSA
}
func NewVoteManager(eth Backend, chainconfig *params.ChainConfig, chain *core.BlockChain, pool *VotePool, journalPath, blsPasswordPath, blsWalletPath string, engine consensus.PoSA) (*VoteManager, error) {
func NewVoteManager(eth Backend, chain *core.BlockChain, pool *VotePool, journalPath, blsPasswordPath, blsWalletPath string, engine consensus.PoSA) (*VoteManager, error) {
voteManager := &VoteManager{
eth: eth,
chain: chain,
chainconfig: chainconfig,
chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
syncVoteCh: make(chan core.NewVoteEvent, voteBufferForPut),
pool: pool,

@ -13,7 +13,6 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/params"
)
const (
@ -45,7 +44,6 @@ type VoteBox struct {
type VotePool struct {
chain *core.BlockChain
chainconfig *params.ChainConfig
mu sync.RWMutex
votesFeed event.Feed
@ -69,10 +67,9 @@ type VotePool struct {
type votesPriorityQueue []*types.VoteData
func NewVotePool(chainconfig *params.ChainConfig, chain *core.BlockChain, engine consensus.PoSA) *VotePool {
func NewVotePool(chain *core.BlockChain, engine consensus.PoSA) *VotePool {
votePool := &VotePool{
chain: chain,
chainconfig: chainconfig,
receivedVotes: mapset.NewSet[common.Hash](),
curVotes: make(map[common.Hash]*VoteBox),
futureVotes: make(map[common.Hash]*VoteBox),

@ -160,7 +160,7 @@ func testVotePool(t *testing.T, isValidRules bool) {
}
// Create vote pool
votePool := NewVotePool(params.TestChainConfig, chain, mockEngine)
votePool := NewVotePool(chain, mockEngine)
// Create vote manager
// Create a temporary file for the votes journal
@ -175,7 +175,7 @@ func testVotePool(t *testing.T, isValidRules bool) {
file.Close()
os.Remove(journal)
voteManager, err := NewVoteManager(newTestBackend(), params.TestChainConfig, chain, votePool, journal, walletPasswordDir, walletDir, mockEngine)
voteManager, err := NewVoteManager(newTestBackend(), chain, votePool, journal, walletPasswordDir, walletDir, mockEngine)
if err != nil {
t.Fatalf("failed to create vote managers")
}

@ -22,7 +22,6 @@ import (
"fmt"
"math/big"
"runtime"
"strings"
"sync"
"github.com/ethereum/go-ethereum/accounts"
@ -64,7 +63,6 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie"
)
// Config contains the configuration options of the ETH protocol.
@ -148,21 +146,13 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
if err != nil {
return nil, err
}
chainConfig, genesisHash, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, trie.NewDatabase(chainDb), config.Genesis, nil)
if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok {
return nil, genesisErr
}
log.Info("")
log.Info(strings.Repeat("-", 153))
for _, line := range strings.Split(chainConfig.Description(), "\n") {
log.Info(line)
}
log.Info(strings.Repeat("-", 153))
log.Info("")
if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb, config.TriesInMemory); err != nil {
log.Error("Failed to recover state", "error", err)
}
chainConfig, genesisHash, err := core.LoadChainConfig(chainDb, config.Genesis)
if err != nil {
return nil, err
}
eth := &Ethereum{
config: config,
@ -253,7 +243,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
if config.BlobPool.Datadir != "" {
config.BlobPool.Datadir = stack.ResolvePath(config.BlobPool.Datadir)
}
// TODO: blob is not ready now, it will cause panic.
// TODO(Nathan): blob is not ready now, it will cause panic.
// blobPool := blobpool.New(config.BlobPool, eth.blockchain)
if config.TxPool.Journal != "" {
@ -261,7 +251,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
}
legacyPool := legacypool.New(config.TxPool, eth.blockchain)
// eth.txPool, err = txpool.New(new(big.Int).SetUint64(config.TxPool.PriceLimit), eth.blockchain, []txpool.SubPool{legacyPool, blobPool})
// TODO(Nathan): eth.txPool, err = txpool.New(new(big.Int).SetUint64(config.TxPool.PriceLimit), eth.blockchain, []txpool.SubPool{legacyPool, blobPool})
eth.txPool, err = txpool.New(new(big.Int).SetUint64(config.TxPool.PriceLimit), eth.blockchain, []txpool.SubPool{legacyPool})
if err != nil {
return nil, err
@ -291,7 +281,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
// Create voteManager instance
if posa, ok := eth.engine.(consensus.PoSA); ok {
// Create votePool instance
votePool := vote.NewVotePool(chainConfig, eth.blockchain, posa)
votePool := vote.NewVotePool(eth.blockchain, posa)
eth.votePool = votePool
if parlia, ok := eth.engine.(*parlia.Parlia); ok {
if !config.Miner.DisableVoteAttestation {
@ -313,7 +303,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
blsPasswordPath := stack.ResolvePath(conf.BLSPasswordFile)
blsWalletPath := stack.ResolvePath(conf.BLSWalletDir)
voteJournalPath := stack.ResolvePath(conf.VoteJournalDir)
if _, err := vote.NewVoteManager(eth, chainConfig, eth.blockchain, votePool, voteJournalPath, blsPasswordPath, blsWalletPath, posa); err != nil {
if _, err := vote.NewVoteManager(eth, eth.blockchain, votePool, voteJournalPath, blsPasswordPath, blsWalletPath, posa); err != nil {
log.Error("Failed to Initialize voteManager", "err", err)
return nil, err
}

@ -330,9 +330,9 @@ func (d *Downloader) UnregisterPeer(id string) error {
return nil
}
// Synchronise tries to sync up our local blockchain with a remote peer, both
// LegacySync tries to sync up our local blockchain with a remote peer, both
// adding various sanity checks and wrapping it with various log entries.
func (d *Downloader) Synchronise(id string, head common.Hash, td *big.Int, ttd *big.Int, mode SyncMode) error {
func (d *Downloader) LegacySync(id string, head common.Hash, td *big.Int, ttd *big.Int, mode SyncMode) error {
err := d.synchronise(id, head, td, ttd, mode, false, nil)
switch err {

@ -1034,7 +1034,7 @@ func testBlockHeaderAttackerDropping(t *testing.T, protocol uint) {
// Simulate a synchronisation and check the required result
tester.downloader.synchroniseMock = func(string, common.Hash) error { return tt.result }
tester.downloader.Synchronise(id, tester.chain.Genesis().Hash(), big.NewInt(1000), nil, FullSync)
tester.downloader.LegacySync(id, tester.chain.Genesis().Hash(), big.NewInt(1000), nil, FullSync)
if _, ok := tester.peers[id]; !ok != tt.drop {
t.Errorf("test %d: peer drop mismatch for %v: have %v, want %v", i, tt.result, !ok, tt.drop)
}

@ -797,6 +797,7 @@ func TestOptionMaxPeersPerIP(t *testing.T) {
defer sink.Close()
wg.Add(1)
time.Sleep(time.Duration((tryNum-1)*200) * time.Millisecond)
go func(num int) {
err := handler.handler.runEthPeer(sink, func(peer *eth.Peer) error {
wg.Done()

@ -242,7 +242,7 @@ func (h *handler) doSync(op *chainSyncOp) error {
}
}
// Run the sync cycle, and disable snap sync if we're past the pivot block
err := h.downloader.Synchronise(op.peer.ID(), op.head, op.td, h.chain.Config().TerminalTotalDifficulty, op.mode)
err := h.downloader.LegacySync(op.peer.ID(), op.head, op.td, h.chain.Config().TerminalTotalDifficulty, op.mode)
if err != nil {
return err
}

@ -19,7 +19,6 @@ package les
import (
"errors"
"strings"
"time"
"github.com/ethereum/go-ethereum/accounts"
@ -107,6 +106,9 @@ func New(stack *node.Node, config *ethconfig.Config) (*LightEthereum, error) {
if err != nil {
return nil, err
}
log.Info("Initialised chain configuration for les.client", "config", chainConfig)
// Description of chainConfig is empty now
/*
log.Info("")
log.Info(strings.Repeat("-", 153))
for _, line := range strings.Split(chainConfig.Description(), "\n") {
@ -114,6 +116,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*LightEthereum, error) {
}
log.Info(strings.Repeat("-", 153))
log.Info("")
*/
peers := newServerPeerSet()
merger := consensus.NewMerger(chainDb)

@ -259,7 +259,7 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus
// Sanitize the timeout config for creating payload.
newpayloadTimeout := worker.config.NewPayloadTimeout
if newpayloadTimeout == 0 {
log.Warn("Sanitizing new payload timeout to default", "provided", newpayloadTimeout, "updated", DefaultConfig.NewPayloadTimeout)
// log.Warn("Sanitizing new payload timeout to default", "provided", newpayloadTimeout, "updated", DefaultConfig.NewPayloadTimeout)
newpayloadTimeout = DefaultConfig.NewPayloadTimeout
}
if newpayloadTimeout < time.Millisecond*100 {

@ -140,7 +140,7 @@ func New(diskdb ethdb.Database, config *Config) *Database {
// mechanism also ensures that at most one **non-readOnly** database
// is opened at the same time to prevent accidental mutation.
if ancient, err := diskdb.AncientDatadir(); err == nil && ancient != "" && !db.readOnly {
offset := uint64(0) //TODO(Nathan)
offset := uint64(0) //TODO(Nathan): just for passing compilation
freezer, err := rawdb.NewStateHistoryFreezer(ancient, false, offset)
if err != nil {
log.Crit("Failed to open state history freezer", "err", err)