mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 17:33:47 +00:00
cmd, core, miner: rework genesis initialization
This commit is contained in:
parent
5065e6c935
commit
d1460c1433
11 changed files with 191 additions and 150 deletions
|
|
@ -230,11 +230,10 @@ func initGenesis(ctx *cli.Context) error {
|
|||
triedb := utils.MakeTrieDatabase(ctx, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle())
|
||||
defer triedb.Close()
|
||||
|
||||
_, hash, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides)
|
||||
_, hash, _, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides)
|
||||
if err != nil {
|
||||
utils.Fatalf("Failed to write genesis block: %v", err)
|
||||
}
|
||||
|
||||
log.Info("Successfully wrote genesis state", "database", "chaindata", "hash", hash)
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ func TestHistoryImportAndExport(t *testing.T) {
|
|||
db2.Close()
|
||||
})
|
||||
|
||||
genesis.MustCommit(db2, triedb.NewDatabase(db, triedb.HashDefaults))
|
||||
genesis.MustCommit(db2, triedb.NewDatabase(db2, triedb.HashDefaults))
|
||||
imported, err := core.NewBlockChain(db2, nil, genesis, nil, ethash.NewFaker(), vm.Config{}, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to initialize chain: %v", err)
|
||||
|
|
|
|||
|
|
@ -269,14 +269,19 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
|||
cacheConfig = defaultCacheConfig
|
||||
}
|
||||
// Open trie database with provided config
|
||||
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(genesis != nil && genesis.IsVerkle()))
|
||||
enableVerkle, err := EnableVerkleAtGenesis(db, genesis)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(enableVerkle))
|
||||
|
||||
// Setup the genesis block, commit the provided genesis specification
|
||||
// to database if the genesis block is not present yet, or load the
|
||||
// stored one from database.
|
||||
chainConfig, genesisHash, genesisErr := SetupGenesisBlockWithOverride(db, triedb, genesis, overrides)
|
||||
if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok {
|
||||
return nil, genesisErr
|
||||
// Write the supplied genesis to the database if it has not been initialized
|
||||
// yet. The corresponding chain config will be returned, either from the
|
||||
// provided genesis or from the locally stored configuration if the genesis
|
||||
// has already been initialized.
|
||||
chainConfig, genesisHash, compatErr, err := SetupGenesisBlockWithOverride(db, triedb, genesis, overrides)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Info("")
|
||||
log.Info(strings.Repeat("-", 153))
|
||||
|
|
@ -303,7 +308,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
|||
vmConfig: vmConfig,
|
||||
logger: vmConfig.Tracer,
|
||||
}
|
||||
var err error
|
||||
bc.hc, err = NewHeaderChain(db, chainConfig, engine, bc.insertStopped)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -453,16 +457,15 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
|||
}
|
||||
|
||||
// Rewind the chain in case of an incompatible config upgrade.
|
||||
if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
|
||||
log.Warn("Rewinding chain to upgrade configuration", "err", compat)
|
||||
if compat.RewindToTime > 0 {
|
||||
bc.SetHeadWithTimestamp(compat.RewindToTime)
|
||||
if compatErr != nil {
|
||||
log.Warn("Rewinding chain to upgrade configuration", "err", compatErr)
|
||||
if compatErr.RewindToTime > 0 {
|
||||
bc.SetHeadWithTimestamp(compatErr.RewindToTime)
|
||||
} else {
|
||||
bc.SetHead(compat.RewindToBlock)
|
||||
bc.SetHead(compatErr.RewindToBlock)
|
||||
}
|
||||
rawdb.WriteChainConfig(db, genesisHash, chainConfig)
|
||||
}
|
||||
|
||||
// Start tx indexer if it's enabled.
|
||||
if txLookupLimit != nil {
|
||||
bc.txIndexer = newTxIndexer(*txLookupLimit, bc)
|
||||
|
|
|
|||
202
core/genesis.go
202
core/genesis.go
|
|
@ -239,6 +239,24 @@ type ChainOverrides struct {
|
|||
OverrideVerkle *uint64
|
||||
}
|
||||
|
||||
// apply applies the chain overrides on the supplied chain config.
|
||||
func (o *ChainOverrides) apply(cfg *params.ChainConfig) (*params.ChainConfig, error) {
|
||||
if o == nil || cfg == nil {
|
||||
return cfg, nil
|
||||
}
|
||||
cpy := *cfg
|
||||
if o.OverrideCancun != nil {
|
||||
cpy.CancunTime = o.OverrideCancun
|
||||
}
|
||||
if o.OverrideVerkle != nil {
|
||||
cpy.VerkleTime = o.OverrideVerkle
|
||||
}
|
||||
if err := cpy.CheckConfigForkOrder(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cpy, nil
|
||||
}
|
||||
|
||||
// SetupGenesisBlock writes or updates the genesis block in db.
|
||||
// The block that will be used is:
|
||||
//
|
||||
|
|
@ -250,109 +268,102 @@ type ChainOverrides struct {
|
|||
// The stored chain configuration will be updated if it is compatible (i.e. does not
|
||||
// specify a fork block below the local head block). In case of a conflict, the
|
||||
// error is a *params.ConfigCompatError and the new, unwritten config is returned.
|
||||
//
|
||||
// The returned chain configuration is never nil.
|
||||
func SetupGenesisBlock(db ethdb.Database, triedb *triedb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) {
|
||||
func SetupGenesisBlock(db ethdb.Database, triedb *triedb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
||||
return SetupGenesisBlockWithOverride(db, triedb, genesis, nil)
|
||||
}
|
||||
|
||||
func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, genesis *Genesis, overrides *ChainOverrides) (*params.ChainConfig, common.Hash, error) {
|
||||
func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, genesis *Genesis, overrides *ChainOverrides) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
||||
// Sanitize the supplied genesis, ensuring it has the associated chain
|
||||
// config attached.
|
||||
if genesis != nil && genesis.Config == nil {
|
||||
return params.AllEthashProtocolChanges, common.Hash{}, errGenesisNoConfig
|
||||
return nil, common.Hash{}, nil, errGenesisNoConfig
|
||||
}
|
||||
applyOverrides := func(config *params.ChainConfig) {
|
||||
if config != nil {
|
||||
if overrides != nil && overrides.OverrideCancun != nil {
|
||||
config.CancunTime = overrides.OverrideCancun
|
||||
}
|
||||
if overrides != nil && overrides.OverrideVerkle != nil {
|
||||
config.VerkleTime = overrides.OverrideVerkle
|
||||
}
|
||||
}
|
||||
}
|
||||
// Just commit the new block if there is no stored genesis block.
|
||||
stored := rawdb.ReadCanonicalHash(db, 0)
|
||||
if (stored == common.Hash{}) {
|
||||
// Commit the genesis if the database is empty
|
||||
ghash := rawdb.ReadCanonicalHash(db, 0)
|
||||
if (ghash == common.Hash{}) {
|
||||
if genesis == nil {
|
||||
log.Info("Writing default main-net genesis block")
|
||||
genesis = DefaultGenesisBlock()
|
||||
} else {
|
||||
log.Info("Writing custom genesis block")
|
||||
}
|
||||
chainCfg, err := overrides.apply(genesis.Config)
|
||||
if err != nil {
|
||||
return nil, common.Hash{}, nil, err
|
||||
}
|
||||
genesis.Config = chainCfg
|
||||
|
||||
applyOverrides(genesis.Config)
|
||||
block, err := genesis.Commit(db, triedb)
|
||||
if err != nil {
|
||||
return genesis.Config, common.Hash{}, err
|
||||
return nil, common.Hash{}, nil, err
|
||||
}
|
||||
return genesis.Config, block.Hash(), nil
|
||||
return chainCfg, block.Hash(), nil, nil
|
||||
}
|
||||
// The genesis block is present(perhaps in ancient database) while the
|
||||
// state database is not initialized yet. It can happen that the node
|
||||
// is initialized with an external ancient store. Commit genesis state
|
||||
// in this case.
|
||||
header := rawdb.ReadHeader(db, stored, 0)
|
||||
if header.Root != types.EmptyRootHash && !triedb.Initialized(header.Root) {
|
||||
// Commit the genesis if the genesis block exists in the ancient database
|
||||
// but the key-value database is empty without initializing the genesis
|
||||
// fields. This scenario can occur when the node is created from scratch
|
||||
// with an existing ancient store.
|
||||
storedCfg := rawdb.ReadChainConfig(db, ghash)
|
||||
if storedCfg == nil {
|
||||
// Ensure the stored genesis block matches with the given genesis. Private
|
||||
// networks must explicitly specify the genesis in the config file, mainnet
|
||||
// genesis will be used as default and the initialization will always fail.
|
||||
if genesis == nil {
|
||||
log.Info("Writing default main-net genesis block")
|
||||
genesis = DefaultGenesisBlock()
|
||||
} else {
|
||||
log.Info("Writing custom genesis block")
|
||||
}
|
||||
applyOverrides(genesis.Config)
|
||||
// Ensure the stored genesis matches with the given one.
|
||||
hash := genesis.ToBlock().Hash()
|
||||
if hash != stored {
|
||||
return genesis.Config, hash, &GenesisMismatchError{stored, hash}
|
||||
chainCfg, err := overrides.apply(genesis.Config)
|
||||
if 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}
|
||||
}
|
||||
block, err := genesis.Commit(db, triedb)
|
||||
if err != nil {
|
||||
return genesis.Config, hash, err
|
||||
return nil, common.Hash{}, nil, err
|
||||
}
|
||||
return genesis.Config, block.Hash(), nil
|
||||
return chainCfg, block.Hash(), nil, nil
|
||||
}
|
||||
// Check whether the genesis block is already written.
|
||||
// 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 {
|
||||
applyOverrides(genesis.Config)
|
||||
hash := genesis.ToBlock().Hash()
|
||||
if hash != stored {
|
||||
return genesis.Config, hash, &GenesisMismatchError{stored, hash}
|
||||
chainCfg, err := overrides.apply(genesis.Config)
|
||||
if 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}
|
||||
}
|
||||
}
|
||||
// Get the existing chain configuration.
|
||||
newcfg := genesis.configOrDefault(stored)
|
||||
applyOverrides(newcfg)
|
||||
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")
|
||||
rawdb.WriteChainConfig(db, stored, newcfg)
|
||||
return newcfg, stored, nil
|
||||
}
|
||||
storedData, _ := json.Marshal(storedcfg)
|
||||
// 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
|
||||
// on top of an existing private network genesis block). In that case, only
|
||||
// apply the overrides.
|
||||
if genesis == nil && stored != params.MainnetGenesisHash {
|
||||
newcfg = storedcfg
|
||||
applyOverrides(newcfg)
|
||||
}
|
||||
// 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)
|
||||
if head == nil {
|
||||
return newcfg, stored, errors.New("missing head header")
|
||||
return nil, common.Hash{}, nil, errors.New("missing head header")
|
||||
}
|
||||
compatErr := storedcfg.CheckCompatible(newcfg, head.Number.Uint64(), head.Time)
|
||||
newCfg := genesis.chainConfigOrDefault(ghash, storedCfg)
|
||||
|
||||
// TODO(rjl493456442) better to define the comparator of chain config
|
||||
// and short circuit if the chain config is not changed.
|
||||
compatErr := storedCfg.CheckCompatible(newCfg, head.Number.Uint64(), head.Time)
|
||||
if compatErr != nil && ((head.Number.Uint64() != 0 && compatErr.RewindToBlock != 0) || (head.Time != 0 && compatErr.RewindToTime != 0)) {
|
||||
return newcfg, stored, compatErr
|
||||
return newCfg, ghash, compatErr, nil
|
||||
}
|
||||
// Don't overwrite if the old is identical to the new
|
||||
if newData, _ := json.Marshal(newcfg); !bytes.Equal(storedData, newData) {
|
||||
rawdb.WriteChainConfig(db, stored, newcfg)
|
||||
// Don't overwrite if the old is identical to the new. It's useful
|
||||
// for the scenarios that database is opened in the read-only mode.
|
||||
storedData, _ := json.Marshal(storedCfg)
|
||||
if newData, _ := json.Marshal(newCfg); !bytes.Equal(storedData, newData) {
|
||||
rawdb.WriteChainConfig(db, ghash, newCfg)
|
||||
}
|
||||
return newcfg, stored, nil
|
||||
return newCfg, ghash, nil, nil
|
||||
}
|
||||
|
||||
// LoadChainConfig loads the stored chain config if it is already present in
|
||||
|
|
@ -388,7 +399,10 @@ func LoadChainConfig(db ethdb.Database, genesis *Genesis) (*params.ChainConfig,
|
|||
return params.MainnetChainConfig, nil
|
||||
}
|
||||
|
||||
func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
|
||||
// chainConfigOrDefault retrieves the attached chain configuration. If the genesis
|
||||
// object is null, it returns the default chain configuration based on the given
|
||||
// genesis hash, or the locally stored config if it's not a pre-defined network.
|
||||
func (g *Genesis) chainConfigOrDefault(ghash common.Hash, stored *params.ChainConfig) *params.ChainConfig {
|
||||
switch {
|
||||
case g != nil:
|
||||
return g.Config
|
||||
|
|
@ -399,14 +413,14 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
|
|||
case ghash == params.SepoliaGenesisHash:
|
||||
return params.SepoliaChainConfig
|
||||
default:
|
||||
return params.AllEthashProtocolChanges
|
||||
return stored
|
||||
}
|
||||
}
|
||||
|
||||
// IsVerkle indicates whether the state is already stored in a verkle
|
||||
// tree at genesis time.
|
||||
func (g *Genesis) IsVerkle() bool {
|
||||
return g.Config.IsVerkle(new(big.Int).SetUint64(g.Number), g.Timestamp)
|
||||
return g.Config.IsVerkleGenesis()
|
||||
}
|
||||
|
||||
// ToBlock returns the genesis block according to genesis specification.
|
||||
|
|
@ -486,7 +500,7 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Blo
|
|||
}
|
||||
config := g.Config
|
||||
if config == nil {
|
||||
config = params.AllEthashProtocolChanges
|
||||
return nil, errors.New("invalid genesis without chain config")
|
||||
}
|
||||
if err := config.CheckConfigForkOrder(); err != nil {
|
||||
return nil, err
|
||||
|
|
@ -506,16 +520,17 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Blo
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rawdb.WriteGenesisStateSpec(db, block.Hash(), blob)
|
||||
rawdb.WriteTd(db, block.Hash(), block.NumberU64(), block.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())
|
||||
rawdb.WriteChainConfig(db, block.Hash(), config)
|
||||
return block, nil
|
||||
batch := db.NewBatch()
|
||||
rawdb.WriteGenesisStateSpec(batch, block.Hash(), blob)
|
||||
rawdb.WriteTd(batch, block.Hash(), block.NumberU64(), block.Difficulty())
|
||||
rawdb.WriteBlock(batch, block)
|
||||
rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), nil)
|
||||
rawdb.WriteCanonicalHash(batch, block.Hash(), block.NumberU64())
|
||||
rawdb.WriteHeadBlockHash(batch, block.Hash())
|
||||
rawdb.WriteHeadFastBlockHash(batch, block.Hash())
|
||||
rawdb.WriteHeadHeaderHash(batch, block.Hash())
|
||||
rawdb.WriteChainConfig(batch, block.Hash(), config)
|
||||
return block, batch.Write()
|
||||
}
|
||||
|
||||
// MustCommit writes the genesis block and state to db, panicking on error.
|
||||
|
|
@ -528,6 +543,29 @@ func (g *Genesis) MustCommit(db ethdb.Database, triedb *triedb.Database) *types.
|
|||
return block
|
||||
}
|
||||
|
||||
// EnableVerkleAtGenesis indicates whether the verkle fork should be activated
|
||||
// at genesis. This is a temporary solution only for verkle devnet testing, where
|
||||
// verkle fork is activated at genesis, and the configured activation date has
|
||||
// already passed.
|
||||
//
|
||||
// In production networks (mainnet and public testnets), verkle activation always
|
||||
// occurs after the genesis block, making this function irrelevant in those cases.
|
||||
func EnableVerkleAtGenesis(db ethdb.Database, genesis *Genesis) (bool, error) {
|
||||
if genesis != nil {
|
||||
if genesis.Config == nil {
|
||||
return false, errGenesisNoConfig
|
||||
}
|
||||
return genesis.Config.EnableVerkleAtGenesis, nil
|
||||
}
|
||||
if ghash := rawdb.ReadCanonicalHash(db, 0); ghash != (common.Hash{}) {
|
||||
chainCfg := rawdb.ReadChainConfig(db, ghash)
|
||||
if chainCfg != nil {
|
||||
return chainCfg.EnableVerkleAtGenesis, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// DefaultGenesisBlock returns the Ethereum main net genesis block.
|
||||
func DefaultGenesisBlock() *Genesis {
|
||||
return &Genesis{
|
||||
|
|
|
|||
|
|
@ -54,23 +54,23 @@ func testSetupGenesis(t *testing.T, scheme string) {
|
|||
oldcustomg.Config = ¶ms.ChainConfig{HomesteadBlock: big.NewInt(2)}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
fn func(ethdb.Database) (*params.ChainConfig, common.Hash, error)
|
||||
wantConfig *params.ChainConfig
|
||||
wantHash common.Hash
|
||||
wantErr error
|
||||
name string
|
||||
fn func(ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error)
|
||||
wantConfig *params.ChainConfig
|
||||
wantHash common.Hash
|
||||
wantErr error
|
||||
wantCompactErr *params.ConfigCompatError
|
||||
}{
|
||||
{
|
||||
name: "genesis without ChainConfig",
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
||||
return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), new(Genesis))
|
||||
},
|
||||
wantErr: errGenesisNoConfig,
|
||||
wantConfig: params.AllEthashProtocolChanges,
|
||||
wantErr: errGenesisNoConfig,
|
||||
},
|
||||
{
|
||||
name: "no block in DB, genesis == nil",
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
||||
return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), nil)
|
||||
},
|
||||
wantHash: params.MainnetGenesisHash,
|
||||
|
|
@ -78,7 +78,7 @@ func testSetupGenesis(t *testing.T, scheme string) {
|
|||
},
|
||||
{
|
||||
name: "mainnet block in DB, genesis == nil",
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
||||
DefaultGenesisBlock().MustCommit(db, triedb.NewDatabase(db, newDbConfig(scheme)))
|
||||
return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), nil)
|
||||
},
|
||||
|
|
@ -87,7 +87,7 @@ func testSetupGenesis(t *testing.T, scheme string) {
|
|||
},
|
||||
{
|
||||
name: "custom block in DB, genesis == nil",
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
||||
tdb := triedb.NewDatabase(db, newDbConfig(scheme))
|
||||
customg.Commit(db, tdb)
|
||||
return SetupGenesisBlock(db, tdb, nil)
|
||||
|
|
@ -97,18 +97,16 @@ func testSetupGenesis(t *testing.T, scheme string) {
|
|||
},
|
||||
{
|
||||
name: "custom block in DB, genesis == sepolia",
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
||||
tdb := triedb.NewDatabase(db, newDbConfig(scheme))
|
||||
customg.Commit(db, tdb)
|
||||
return SetupGenesisBlock(db, tdb, DefaultSepoliaGenesisBlock())
|
||||
},
|
||||
wantErr: &GenesisMismatchError{Stored: customghash, New: params.SepoliaGenesisHash},
|
||||
wantHash: params.SepoliaGenesisHash,
|
||||
wantConfig: params.SepoliaChainConfig,
|
||||
wantErr: &GenesisMismatchError{Stored: customghash, New: params.SepoliaGenesisHash},
|
||||
},
|
||||
{
|
||||
name: "compatible config in DB",
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
||||
tdb := triedb.NewDatabase(db, newDbConfig(scheme))
|
||||
oldcustomg.Commit(db, tdb)
|
||||
return SetupGenesisBlock(db, tdb, &customg)
|
||||
|
|
@ -118,7 +116,7 @@ func testSetupGenesis(t *testing.T, scheme string) {
|
|||
},
|
||||
{
|
||||
name: "incompatible config in DB",
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
||||
// Commit the 'old' genesis block with Homestead transition at #2.
|
||||
// Advance to block #4, past the homestead transition block of customg.
|
||||
tdb := triedb.NewDatabase(db, newDbConfig(scheme))
|
||||
|
|
@ -135,7 +133,7 @@ func testSetupGenesis(t *testing.T, scheme string) {
|
|||
},
|
||||
wantHash: customghash,
|
||||
wantConfig: customg.Config,
|
||||
wantErr: ¶ms.ConfigCompatError{
|
||||
wantCompactErr: ¶ms.ConfigCompatError{
|
||||
What: "Homestead fork block",
|
||||
StoredBlock: big.NewInt(2),
|
||||
NewBlock: big.NewInt(3),
|
||||
|
|
@ -146,12 +144,16 @@ func testSetupGenesis(t *testing.T, scheme string) {
|
|||
|
||||
for _, test := range tests {
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
config, hash, err := test.fn(db)
|
||||
config, hash, compatErr, err := test.fn(db)
|
||||
// Check the return values.
|
||||
if !reflect.DeepEqual(err, test.wantErr) {
|
||||
spew := spew.ConfigState{DisablePointerAddresses: true, DisableCapacities: true}
|
||||
t.Errorf("%s: returned error %#v, want %#v", test.name, spew.NewFormatter(err), spew.NewFormatter(test.wantErr))
|
||||
}
|
||||
if !reflect.DeepEqual(compatErr, test.wantCompactErr) {
|
||||
spew := spew.ConfigState{DisablePointerAddresses: true, DisableCapacities: true}
|
||||
t.Errorf("%s: returned error %#v, want %#v", test.name, spew.NewFormatter(compatErr), spew.NewFormatter(test.wantCompactErr))
|
||||
}
|
||||
if !reflect.DeepEqual(config, test.wantConfig) {
|
||||
t.Errorf("%s:\nreturned %v\nwant %v", test.name, config, test.wantConfig)
|
||||
}
|
||||
|
|
@ -279,6 +281,7 @@ func TestVerkleGenesisCommit(t *testing.T) {
|
|||
PragueTime: &verkleTime,
|
||||
VerkleTime: &verkleTime,
|
||||
TerminalTotalDifficulty: big.NewInt(0),
|
||||
EnableVerkleAtGenesis: true,
|
||||
Ethash: nil,
|
||||
Clique: nil,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ var (
|
|||
ShanghaiTime: u64(0),
|
||||
VerkleTime: u64(0),
|
||||
TerminalTotalDifficulty: common.Big0,
|
||||
EnableVerkleAtGenesis: true,
|
||||
// TODO uncomment when proof generation is merged
|
||||
// ProofInBlocks: true,
|
||||
}
|
||||
|
|
@ -77,6 +78,7 @@ var (
|
|||
ShanghaiTime: u64(0),
|
||||
VerkleTime: u64(0),
|
||||
TerminalTotalDifficulty: common.Big0,
|
||||
EnableVerkleAtGenesis: true,
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ func createMiner(t *testing.T) *Miner {
|
|||
chainDB := rawdb.NewMemoryDatabase()
|
||||
triedb := triedb.NewDatabase(chainDB, nil)
|
||||
genesis := minerTestGenesisBlock(15, 11_500_000, common.HexToAddress("12345"))
|
||||
chainConfig, _, err := core.SetupGenesisBlock(chainDB, triedb, genesis)
|
||||
chainConfig, _, _, err := core.SetupGenesisBlock(chainDB, triedb, genesis)
|
||||
if err != nil {
|
||||
t.Fatalf("can't create new chain config: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -326,6 +326,19 @@ type ChainConfig struct {
|
|||
|
||||
DepositContractAddress common.Address `json:"depositContractAddress,omitempty"`
|
||||
|
||||
// EnableVerkleAtGenesis is a flag that specifies whether the network uses
|
||||
// the Verkle tree starting from the genesis block. If set to true, the
|
||||
// genesis state will be committed using the Verkle tree, eliminating the
|
||||
// need for any Verkle transition later.
|
||||
//
|
||||
// This is a temporary flag only for verkle devnet testing, where verkle is
|
||||
// activated at genesis, and the configured activation date has already passed.
|
||||
//
|
||||
// In production networks (mainnet and public testnets), verkle activation
|
||||
// always occurs after the genesis block, making this flag irrelevant in
|
||||
// those cases.
|
||||
EnableVerkleAtGenesis bool `json:"enableVerkleAtGenesis,omitempty"`
|
||||
|
||||
// Various consensus engines
|
||||
Ethash *EthashConfig `json:"ethash,omitempty"`
|
||||
Clique *CliqueConfig `json:"clique,omitempty"`
|
||||
|
|
@ -525,6 +538,20 @@ func (c *ChainConfig) IsVerkle(num *big.Int, time uint64) bool {
|
|||
return c.IsLondon(num) && isTimestampForked(c.VerkleTime, time)
|
||||
}
|
||||
|
||||
// IsVerkleGenesis checks whether the verkle fork is activated at the genesis block.
|
||||
//
|
||||
// Verkle mode is considered enabled if the verkle fork time is configured,
|
||||
// regardless of whether the local time has surpassed the fork activation time.
|
||||
// This is a temporary workaround for verkle devnet testing, where verkle is
|
||||
// activated at genesis, and the configured activation date has already passed.
|
||||
//
|
||||
// In production networks (mainnet and public testnets), verkle activation
|
||||
// always occurs after the genesis block, making this function irrelevant in
|
||||
// those cases.
|
||||
func (c *ChainConfig) IsVerkleGenesis() bool {
|
||||
return c.EnableVerkleAtGenesis
|
||||
}
|
||||
|
||||
// IsEIP4762 returns whether eip 4762 has been activated at given block.
|
||||
func (c *ChainConfig) IsEIP4762(num *big.Int, time uint64) bool {
|
||||
return c.IsVerkle(num, time)
|
||||
|
|
|
|||
|
|
@ -64,10 +64,6 @@ type backend interface {
|
|||
// state. An error will be returned if the specified state is not available.
|
||||
StateReader(root common.Hash) (database.StateReader, error)
|
||||
|
||||
// Initialized returns an indicator if the state data is already initialized
|
||||
// according to the state scheme.
|
||||
Initialized(genesisRoot common.Hash) bool
|
||||
|
||||
// Size returns the current storage size of the diff layers on top of the
|
||||
// disk layer and the storage size of the nodes cached in the disk layer.
|
||||
//
|
||||
|
|
@ -178,12 +174,6 @@ func (db *Database) Size() (common.StorageSize, common.StorageSize, common.Stora
|
|||
return diffs, nodes, preimages
|
||||
}
|
||||
|
||||
// Initialized returns an indicator if the state data is already initialized
|
||||
// according to the state scheme.
|
||||
func (db *Database) Initialized(genesisRoot common.Hash) bool {
|
||||
return db.backend.Initialized(genesisRoot)
|
||||
}
|
||||
|
||||
// Scheme returns the node scheme used in the database.
|
||||
func (db *Database) Scheme() string {
|
||||
if db.config.PathDB != nil {
|
||||
|
|
|
|||
|
|
@ -532,12 +532,6 @@ func (c *cleaner) Delete(key []byte) error {
|
|||
panic("not implemented")
|
||||
}
|
||||
|
||||
// Initialized returns an indicator if state data is already initialized
|
||||
// in hash-based scheme by checking the presence of genesis state.
|
||||
func (db *Database) Initialized(genesisRoot common.Hash) bool {
|
||||
return rawdb.HasLegacyTrieNode(db.diskdb, genesisRoot)
|
||||
}
|
||||
|
||||
// Update inserts the dirty nodes in provided nodeset into database and link the
|
||||
// account trie with multiple storage tries if necessary.
|
||||
func (db *Database) Update(root common.Hash, parent common.Hash, block uint64, nodes *trienode.MergedNodeSet) error {
|
||||
|
|
|
|||
|
|
@ -499,21 +499,6 @@ func (db *Database) Size() (diffs common.StorageSize, nodes common.StorageSize)
|
|||
return diffs, nodes
|
||||
}
|
||||
|
||||
// Initialized returns an indicator if the state data is already
|
||||
// initialized in path-based scheme.
|
||||
func (db *Database) Initialized(genesisRoot common.Hash) bool {
|
||||
var inited bool
|
||||
db.tree.forEach(func(layer layer) {
|
||||
if layer.rootHash() != types.EmptyRootHash {
|
||||
inited = true
|
||||
}
|
||||
})
|
||||
if !inited {
|
||||
inited = rawdb.ReadSnapSyncStatusFlag(db.diskdb) != rawdb.StateSyncUnknown
|
||||
}
|
||||
return inited
|
||||
}
|
||||
|
||||
// modifyAllowed returns the indicator if mutation is allowed. This function
|
||||
// assumes the db.lock is already held.
|
||||
func (db *Database) modifyAllowed() error {
|
||||
|
|
|
|||
Loading…
Reference in a new issue