Skip to content

Commit

Permalink
params: check fork ordering when initializing new genesis, fixes ethe…
Browse files Browse the repository at this point in the history
…reum#20136 (ethereum#20169)

prevent users from misconfiguring their nodes so that fork ordering is not preserved.
  • Loading branch information
holiman authored and enriquefynn committed Feb 15, 2021
1 parent a26eb08 commit 29c5584
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 7 deletions.
5 changes: 3 additions & 2 deletions core/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1318,7 +1318,7 @@ func TestEIP155Transition(t *testing.T) {
funds = big.NewInt(1000000000)
deleteAddr = common.Address{1}
gspec = &Genesis{
Config: &params.ChainConfig{ChainID: big.NewInt(1), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)},
Config: &params.ChainConfig{ChainID: big.NewInt(1), EIP150Block: big.NewInt(0), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)},
Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}},
}
genesis = gspec.MustCommit(db)
Expand Down Expand Up @@ -1389,7 +1389,7 @@ func TestEIP155Transition(t *testing.T) {
}

// generate an invalid chain id transaction
config := &params.ChainConfig{ChainID: big.NewInt(2), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}
config := &params.ChainConfig{ChainID: big.NewInt(2), EIP150Block: big.NewInt(0), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}
blocks, _ = GenerateChain(config, blocks[len(blocks)-1], ethash.NewFaker(), db, 4, func(i int, block *BlockGen) {
var (
tx *types.Transaction
Expand Down Expand Up @@ -1425,6 +1425,7 @@ func TestEIP161AccountRemoval(t *testing.T) {
ChainID: big.NewInt(1),
HomesteadBlock: new(big.Int),
EIP155Block: new(big.Int),
EIP150Block: new(big.Int),
EIP158Block: big.NewInt(2),
},
Alloc: GenesisAlloc{address: {Balance: funds}},
Expand Down
15 changes: 10 additions & 5 deletions core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, override
if overrideIstanbul != nil {
newcfg.IstanbulBlock = overrideIstanbul
}
if err := newcfg.CheckConfigForkOrder(); err != nil {
return newcfg, common.Hash{}, err
}
storedcfg := rawdb.ReadChainConfig(db, stored)
if storedcfg == nil {
log.Warn("Found genesis block without chain config")
Expand Down Expand Up @@ -295,18 +298,20 @@ func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) {
if block.Number().Sign() != 0 {
return nil, fmt.Errorf("can't commit genesis block with number > 0")
}
config := g.Config
if config == nil {
config = params.AllEthashProtocolChanges
}
if err := config.CheckConfigForkOrder(); err != nil {
return nil, err
}
rawdb.WriteTd(db, block.Hash(), block.NumberU64(), g.Difficulty)
rawdb.WriteBlock(db, block)
rawdb.WriteReceipts(db, block.Hash(), block.NumberU64(), nil)
rawdb.WriteCanonicalHash(db, block.Hash(), block.NumberU64())
rawdb.WriteHeadBlockHash(db, block.Hash())
rawdb.WriteHeadFastBlockHash(db, block.Hash())
rawdb.WriteHeadHeaderHash(db, block.Hash())

config := g.Config
if config == nil {
config = params.AllEthashProtocolChanges
}
rawdb.WriteChainConfig(db, block.Hash(), config)
return block, nil
}
Expand Down
36 changes: 36 additions & 0 deletions params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,42 @@ func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64) *Confi
return lasterr
}

// CheckConfigForkOrder checks that we don't "skip" any forks, geth isn't pluggable enough
// to guarantee that forks
func (c *ChainConfig) CheckConfigForkOrder() error {
type fork struct {
name string
block *big.Int
}
var lastFork fork
for _, cur := range []fork{
{"homesteadBlock", c.HomesteadBlock},
{"eip150Block", c.EIP150Block},
{"eip155Block", c.EIP155Block},
{"eip158Block", c.EIP158Block},
{"byzantiumBlock", c.ByzantiumBlock},
{"constantinopleBlock", c.ConstantinopleBlock},
{"petersburgBlock", c.PetersburgBlock},
{"istanbulBlock", c.IstanbulBlock},
} {
if lastFork.name != "" {
// Next one must be higher number
if lastFork.block == nil && cur.block != nil {
return fmt.Errorf("unsupported fork ordering: %v not enabled, but %v enabled at %v",
lastFork.name, cur.name, cur.block)
}
if lastFork.block != nil && cur.block != nil {
if lastFork.block.Cmp(cur.block) > 0 {
return fmt.Errorf("unsupported fork ordering: %v enabled at %v, but %v enabled at %v",
lastFork.name, lastFork.block, cur.name, cur.block)
}
}
}
lastFork = cur
}
return nil
}

func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *ConfigCompatError {
if isForkIncompatible(c.HomesteadBlock, newcfg.HomesteadBlock, head) {
return newCompatError("Homestead fork block", c.HomesteadBlock, newcfg.HomesteadBlock)
Expand Down

0 comments on commit 29c5584

Please sign in to comment.