Skip to content

Commit

Permalink
core: Move blockchain head verification after possible rewind (op-geth
Browse files Browse the repository at this point in the history
…ethereum#446)

* core: Move blockchain head verification after possible rewind

If the blockchain needs a rewind due to a config change, it makes more
sense to first perform that rewind and only then check the chain head's
validity. The change in config might cause the loaded chain's head to be
invalid before the rewind.

* log configs at startup

* fix logging
  • Loading branch information
sebastianst authored Dec 11, 2024
1 parent a7e2bc5 commit d5dbfcf
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 5 deletions.
9 changes: 5 additions & 4 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,10 +410,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
}
}
}
// The first thing the node will do is reconstruct the verification data for
// the head block (ethash cache or clique voting snapshot). Might as well do
// it in advance.
bc.engine.VerifyHeader(bc, bc.CurrentHeader())

if bc.logger != nil && bc.logger.OnBlockchainInit != nil {
bc.logger.OnBlockchainInit(chainConfig)
Expand Down Expand Up @@ -467,6 +463,11 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
rawdb.WriteChainConfig(db, genesisHash, chainConfig)
}

// The first thing the node will do is reconstruct the verification data for
// the head block (ethash cache or clique voting snapshot). Might as well do
// it in advance.
bc.engine.VerifyHeader(bc, bc.CurrentHeader())

// Start tx indexer if it's enabled.
if txLookupLimit != nil {
bc.txIndexer = newTxIndexer(*txLookupLimit, bc)
Expand Down
12 changes: 11 additions & 1 deletion core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
// Get the existing chain configuration.
newcfg := genesis.configOrDefault(stored)
applyOverrides(newcfg)

if err := newcfg.CheckConfigForkOrder(); err != nil {
return newcfg, common.Hash{}, err
}
Expand All @@ -390,7 +391,9 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
rawdb.WriteChainConfig(db, stored, newcfg)
return newcfg, stored, nil
}

storedData, _ := json.Marshal(storedcfg)
log.Info("Stored config", "json", string(storedData))
// Special case: if a private network is being used (no genesis and also no
// mainnet hash in the database), we must not apply the `configOrDefault`
// chain config as that would be AllProtocolChanges (applying any new fork
Expand All @@ -400,6 +403,9 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
newcfg = storedcfg
applyOverrides(newcfg)
}
newData, _ := json.Marshal(newcfg)
log.Info("New config", "json", string(newData), "genesis-nil", genesis == nil)

// Check config compatibility and write the config. Compatibility errors
// are returned to the caller unless we're already at block zero.
head := rawdb.ReadHeadHeader(db)
Expand All @@ -414,9 +420,13 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
if compatErr != nil && ((head.Number.Uint64() != 0 && compatErr.RewindToBlock != 0) || (head.Time != 0 && compatErr.RewindToTime != 0)) {
return newcfg, stored, compatErr
}

// Don't overwrite if the old is identical to the new
if newData, _ := json.Marshal(newcfg); !bytes.Equal(storedData, newData) {
if !bytes.Equal(storedData, newData) {
log.Info("Configs differ")
rawdb.WriteChainConfig(db, stored, newcfg)
} else {
log.Info("Configs equal")
}
return newcfg, stored, nil
}
Expand Down
2 changes: 2 additions & 0 deletions params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params/forks"
)

Expand Down Expand Up @@ -709,6 +710,7 @@ func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height, time uint64,
var lasterr *ConfigCompatError
for {
err := c.checkCompatible(newcfg, bhead, btime, genesisTimestamp)
log.Info("Checking compatibility", "height", bhead, "time", btime, "error", err)
if err == nil || (lasterr != nil && err.RewindToBlock == lasterr.RewindToBlock && err.RewindToTime == lasterr.RewindToTime) {
break
}
Expand Down
12 changes: 12 additions & 0 deletions params/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,18 @@ func TestCheckCompatible(t *testing.T) {
RewindToTime: 9,
},
},
{
stored: &ChainConfig{HoloceneTime: newUint64(10)},
new: &ChainConfig{HoloceneTime: newUint64(20)},
headTimestamp: 15,
genesisTimestamp: newUint64(5),
wantErr: &ConfigCompatError{
What: "Holocene fork timestamp",
StoredTime: newUint64(10),
NewTime: newUint64(20),
RewindToTime: 9,
},
},
}

for i, test := range tests {
Expand Down

0 comments on commit d5dbfcf

Please sign in to comment.