diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 87863750615ab..221b06bb9e58d 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -192,7 +192,7 @@ func initGenesis(ctx *cli.Context) error { if err != nil { utils.Fatalf("Failed to open database: %v", err) } - _, hash, err := core.SetupGenesisBlock(chaindb, genesis) + _, hash, err := core.SetupGenesisBlock(chaindb, genesis, ctx.Bool(utils.CachePreimagesFlag.Name)) if err != nil { utils.Fatalf("Failed to write genesis block: %v", err) } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index efea9349250d9..0969e31bab1b2 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1955,6 +1955,10 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash) } } + + if cfg.Genesis != nil { + cfg.Genesis.UsePreimages = ctx.IsSet(CachePreimagesFlag.Name) + } } // SetDNSDiscoveryDefaults configures DNS discovery with the given URL if @@ -2138,6 +2142,7 @@ func MakeGenesis(ctx *cli.Context) *core.Genesis { case ctx.Bool(DeveloperFlag.Name): Fatalf("Developer chains are ephemeral") } + genesis.UsePreimages = ctx.Bool(CachePreimagesFlag.Name) return genesis } @@ -2145,7 +2150,7 @@ func MakeGenesis(ctx *cli.Context) *core.Genesis { func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) { var err error chainDb = MakeChainDatabase(ctx, stack, false) // TODO(rjl493456442) support read-only database - config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx)) + config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx), ctx.Bool(CachePreimagesFlag.Name)) if err != nil { Fatalf("%v", err) } diff --git a/core/blockchain.go b/core/blockchain.go index f35de404619b3..76c57201503d4 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -595,7 +595,11 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, root common.Hash, repair bo // if the historical chain pruning is enabled. In that case the logic // needs to be improved here. if !bc.HasState(bc.genesisBlock.Root()) { - if err := CommitGenesisState(bc.db, bc.genesisBlock.Hash()); err != nil { + state, err := bc.State() + if err != nil { + log.Crit("Failed to get state database in reorg through genesis", "err", err) + } + if err = CommitGenesisState(bc.db, bc.genesisBlock.Hash(), state.Preimages() != nil); err != nil { log.Crit("Failed to commit genesis state", "err", err) } log.Debug("Recommitted genesis state to disk") diff --git a/core/genesis.go b/core/genesis.go index 71214e84f5058..2241751d82de4 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -63,6 +63,8 @@ type Genesis struct { GasUsed uint64 `json:"gasUsed"` ParentHash common.Hash `json:"parentHash"` BaseFee *big.Int `json:"baseFeePerGas"` + + UsePreimages bool } // GenesisAlloc specifies the initial state that is part of the genesis block. @@ -103,8 +105,8 @@ func (ga *GenesisAlloc) deriveHash() (common.Hash, error) { // flush is very similar with deriveHash, but the main difference is // all the generated states will be persisted into the given database. // Also, the genesis state specification will be flushed as well. -func (ga *GenesisAlloc) flush(db ethdb.Database) error { - statedb, err := state.New(common.Hash{}, state.NewDatabase(db), nil) +func (ga *GenesisAlloc) flush(db ethdb.Database, preimages bool) error { + statedb, err := state.New(common.Hash{}, state.NewDatabaseWithConfig(db, &trie.Config{Preimages: preimages}), nil) if err != nil { return err } @@ -135,7 +137,7 @@ func (ga *GenesisAlloc) flush(db ethdb.Database) error { // CommitGenesisState loads the stored genesis state with the given block // hash and commits them into the given database handler. -func CommitGenesisState(db ethdb.Database, hash common.Hash) error { +func CommitGenesisState(db ethdb.Database, hash common.Hash, preimages bool) error { var alloc GenesisAlloc blob := rawdb.ReadGenesisStateSpec(db, hash) if len(blob) != 0 { @@ -167,7 +169,7 @@ func CommitGenesisState(db ethdb.Database, hash common.Hash) error { return errors.New("not found") } } - return alloc.flush(db) + return alloc.flush(db, preimages) } // GenesisAccount is an account in the state of the genesis block. @@ -244,11 +246,11 @@ func (e *GenesisMismatchError) Error() string { // error is a *params.ConfigCompatError and the new, unwritten config is returned. // // The returned chain configuration is never nil. -func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) { - return SetupGenesisBlockWithOverride(db, genesis, nil, nil) +func SetupGenesisBlock(db ethdb.Database, genesis *Genesis, preimages bool) (*params.ChainConfig, common.Hash, error) { + return SetupGenesisBlockWithOverride(db, genesis, nil, nil, preimages) } -func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, overrideTerminalTotalDifficulty *big.Int, overrideTerminalTotalDifficultyPassed *bool) (*params.ChainConfig, common.Hash, error) { +func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, overrideTerminalTotalDifficulty *big.Int, overrideTerminalTotalDifficultyPassed *bool, preimages bool) (*params.ChainConfig, common.Hash, error) { if genesis != nil && genesis.Config == nil { return params.AllEthashProtocolChanges, common.Hash{}, errGenesisNoConfig } @@ -270,6 +272,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, override if genesis == nil { log.Info("Writing default main-net genesis block") genesis = DefaultGenesisBlock() + genesis.UsePreimages = preimages } else { log.Info("Writing custom genesis block") } @@ -418,7 +421,7 @@ func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) { // All the checks has passed, flush the states derived from the genesis // specification as well as the specification itself into the provided // database. - if err := g.Alloc.flush(db); err != nil { + if err := g.Alloc.flush(db, g.UsePreimages); err != nil { return nil, err } rawdb.WriteTd(db, block.Hash(), block.NumberU64(), block.Difficulty()) diff --git a/core/genesis_test.go b/core/genesis_test.go index ba3423e32a08e..17176b260ef61 100644 --- a/core/genesis_test.go +++ b/core/genesis_test.go @@ -60,7 +60,7 @@ func TestSetupGenesis(t *testing.T) { { name: "genesis without ChainConfig", fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { - return SetupGenesisBlock(db, new(Genesis)) + return SetupGenesisBlock(db, new(Genesis), false) }, wantErr: errGenesisNoConfig, wantConfig: params.AllEthashProtocolChanges, @@ -68,7 +68,7 @@ func TestSetupGenesis(t *testing.T) { { name: "no block in DB, genesis == nil", fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { - return SetupGenesisBlock(db, nil) + return SetupGenesisBlock(db, nil, false) }, wantHash: params.MainnetGenesisHash, wantConfig: params.MainnetChainConfig, @@ -77,7 +77,7 @@ func TestSetupGenesis(t *testing.T) { name: "mainnet block in DB, genesis == nil", fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { DefaultGenesisBlock().MustCommit(db) - return SetupGenesisBlock(db, nil) + return SetupGenesisBlock(db, nil, false) }, wantHash: params.MainnetGenesisHash, wantConfig: params.MainnetChainConfig, @@ -86,7 +86,7 @@ func TestSetupGenesis(t *testing.T) { name: "custom block in DB, genesis == nil", fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { customg.MustCommit(db) - return SetupGenesisBlock(db, nil) + return SetupGenesisBlock(db, nil, false) }, wantHash: customghash, wantConfig: customg.Config, @@ -95,7 +95,7 @@ func TestSetupGenesis(t *testing.T) { name: "custom block in DB, genesis == ropsten", fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { customg.MustCommit(db) - return SetupGenesisBlock(db, DefaultRopstenGenesisBlock()) + return SetupGenesisBlock(db, DefaultRopstenGenesisBlock(), false) }, wantErr: &GenesisMismatchError{Stored: customghash, New: params.RopstenGenesisHash}, wantHash: params.RopstenGenesisHash, @@ -105,7 +105,7 @@ func TestSetupGenesis(t *testing.T) { name: "compatible config in DB", fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) { oldcustomg.MustCommit(db) - return SetupGenesisBlock(db, &customg) + return SetupGenesisBlock(db, &customg, false) }, wantHash: customghash, wantConfig: customg.Config, @@ -124,7 +124,7 @@ func TestSetupGenesis(t *testing.T) { bc.InsertChain(blocks) bc.CurrentBlock() // This should return a compatibility error. - return SetupGenesisBlock(db, &customg) + return SetupGenesisBlock(db, &customg, false) }, wantHash: customghash, wantConfig: customg.Config, @@ -219,7 +219,7 @@ func TestReadWriteGenesisAlloc(t *testing.T) { } hash, _ = alloc.deriveHash() ) - alloc.flush(db) + alloc.flush(db, false) var reload GenesisAlloc err := reload.UnmarshalJSON(rawdb.ReadGenesisStateSpec(db, hash)) diff --git a/eth/backend.go b/eth/backend.go index ebe7001c79941..50a4db62c5218 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -137,7 +137,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { if err != nil { return nil, err } - chainConfig, genesisHash, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, config.Genesis, config.OverrideTerminalTotalDifficulty, config.OverrideTerminalTotalDifficultyPassed) + chainConfig, genesisHash, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, config.Genesis, config.OverrideTerminalTotalDifficulty, config.OverrideTerminalTotalDifficultyPassed, config.Preimages) if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { return nil, genesisErr } diff --git a/les/client.go b/les/client.go index 7caaf2c18a587..c762bb6f72ba3 100644 --- a/les/client.go +++ b/les/client.go @@ -93,7 +93,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*LightEthereum, error) { if err != nil { return nil, err } - chainConfig, genesisHash, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, config.Genesis, config.OverrideTerminalTotalDifficulty, config.OverrideTerminalTotalDifficultyPassed) + chainConfig, genesisHash, genesisErr := core.SetupGenesisBlockWithOverride(chainDb, config.Genesis, config.OverrideTerminalTotalDifficulty, config.OverrideTerminalTotalDifficultyPassed, false) if _, isCompat := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !isCompat { return nil, genesisErr } diff --git a/miner/miner_test.go b/miner/miner_test.go index 5bf344fd7076d..1b37ce55ea8b5 100644 --- a/miner/miner_test.go +++ b/miner/miner_test.go @@ -249,7 +249,7 @@ func createMiner(t *testing.T) (*Miner, *event.TypeMux, func(skipMiner bool)) { memdb := memorydb.New() chainDB := rawdb.NewDatabase(memdb) genesis := core.DeveloperGenesisBlock(15, 11_500_000, common.HexToAddress("12345")) - chainConfig, _, err := core.SetupGenesisBlock(chainDB, genesis) + chainConfig, _, err := core.SetupGenesisBlock(chainDB, genesis, false) if err != nil { t.Fatalf("can't create new chain config: %v", err) }