core: copy genesis before modifying (#31097)

This PR fixes a data race in SetupGenesisWithOverride.
This commit is contained in:
Marius van der Wijden 2025-02-04 14:22:30 +01:00 committed by GitHub
parent 0ad0966cec
commit 665c8512f3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 25 additions and 20 deletions

View File

@ -75,6 +75,19 @@ type Genesis struct {
BlobGasUsed *uint64 `json:"blobGasUsed"` // EIP-4844
}
// copy copies the genesis.
func (g *Genesis) copy() *Genesis {
if g != nil {
cpy := *g
if g.Config != nil {
conf := *g.Config
cpy.Config = &conf
}
return &cpy
}
return nil
}
func ReadGenesis(db ethdb.Database) (*Genesis, error) {
var genesis Genesis
stored := rawdb.ReadCanonicalHash(db, 0)
@ -248,21 +261,17 @@ type ChainOverrides struct {
}
// apply applies the chain overrides on the supplied chain config.
func (o *ChainOverrides) apply(cfg *params.ChainConfig) (*params.ChainConfig, error) {
func (o *ChainOverrides) apply(cfg *params.ChainConfig) error {
if o == nil || cfg == nil {
return cfg, nil
return nil
}
cpy := *cfg
if o.OverrideCancun != nil {
cpy.CancunTime = o.OverrideCancun
cfg.CancunTime = o.OverrideCancun
}
if o.OverrideVerkle != nil {
cpy.VerkleTime = o.OverrideVerkle
cfg.VerkleTime = o.OverrideVerkle
}
if err := cpy.CheckConfigForkOrder(); err != nil {
return nil, err
}
return &cpy, nil
return cfg.CheckConfigForkOrder()
}
// SetupGenesisBlock writes or updates the genesis block in db.
@ -281,6 +290,8 @@ func SetupGenesisBlock(db ethdb.Database, triedb *triedb.Database, genesis *Gene
}
func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, genesis *Genesis, overrides *ChainOverrides) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
// Copy the genesis, so we can operate on a copy.
genesis = genesis.copy()
// Sanitize the supplied genesis, ensuring it has the associated chain
// config attached.
if genesis != nil && genesis.Config == nil {
@ -295,17 +306,15 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
} else {
log.Info("Writing custom genesis block")
}
chainCfg, err := overrides.apply(genesis.Config)
if err != nil {
if err := overrides.apply(genesis.Config); err != nil {
return nil, common.Hash{}, nil, err
}
genesis.Config = chainCfg
block, err := genesis.Commit(db, triedb)
if err != nil {
return nil, common.Hash{}, nil, err
}
return chainCfg, block.Hash(), nil, nil
return genesis.Config, block.Hash(), nil, nil
}
// Commit the genesis if the genesis block exists in the ancient database
// but the key-value database is empty without initializing the genesis
@ -322,11 +331,9 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
} else {
log.Info("Writing custom genesis block")
}
chainCfg, err := overrides.apply(genesis.Config)
if err != nil {
if err := overrides.apply(genesis.Config); err != nil {
return nil, common.Hash{}, nil, err
}
genesis.Config = chainCfg
if hash := genesis.ToBlock().Hash(); hash != ghash {
return nil, common.Hash{}, nil, &GenesisMismatchError{ghash, hash}
@ -335,17 +342,15 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
if err != nil {
return nil, common.Hash{}, nil, err
}
return chainCfg, block.Hash(), nil, nil
return genesis.Config, block.Hash(), nil, nil
}
// The genesis block has already been committed previously. Verify that the
// provided genesis with chain overrides matches the existing one, and update
// the stored chain config if necessary.
if genesis != nil {
chainCfg, err := overrides.apply(genesis.Config)
if err != nil {
if err := overrides.apply(genesis.Config); err != nil {
return nil, common.Hash{}, nil, err
}
genesis.Config = chainCfg
if hash := genesis.ToBlock().Hash(); hash != ghash {
return nil, common.Hash{}, nil, &GenesisMismatchError{ghash, hash}