Skip to content

Commit 7227c9e

Browse files
jwasingerholiman
andauthored
cmd/geth: make dumpgenesis load genesis datadir if it exists (#25135)
`geth dumpgenesis` currently does not respect the content of the data directory. Instead, it outputs the genesis block created by command-line flags. This PR fixes it to read the genesis from the database, if the database already exists. Co-authored-by: Martin Holst Swende <[email protected]>
1 parent c55c56c commit 7227c9e

File tree

3 files changed

+80
-11
lines changed

3 files changed

+80
-11
lines changed

cmd/geth/chaincmd.go

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,10 @@ It expects the genesis file as argument.`,
6161
Name: "dumpgenesis",
6262
Usage: "Dumps genesis block JSON configuration to stdout",
6363
ArgsUsage: "",
64-
Flags: utils.NetworkFlags,
64+
Flags: append([]cli.Flag{utils.DataDirFlag}, utils.NetworkFlags...),
6565
Description: `
66-
The dumpgenesis command dumps the genesis block configuration in JSON format to stdout.`,
66+
The dumpgenesis command prints the genesis configuration of the network preset
67+
if one is set. Otherwise it prints the genesis from the datadir.`,
6768
}
6869
importCommand = &cli.Command{
6970
Action: importChain,
@@ -203,14 +204,39 @@ func initGenesis(ctx *cli.Context) error {
203204
}
204205

205206
func dumpGenesis(ctx *cli.Context) error {
206-
// TODO(rjl493456442) support loading from the custom datadir
207-
genesis := utils.MakeGenesis(ctx)
208-
if genesis == nil {
209-
genesis = core.DefaultGenesisBlock()
207+
// if there is a testnet preset enabled, dump that
208+
if utils.IsNetworkPreset(ctx) {
209+
genesis := utils.MakeGenesis(ctx)
210+
if err := json.NewEncoder(os.Stdout).Encode(genesis); err != nil {
211+
utils.Fatalf("could not encode genesis: %s", err)
212+
}
213+
return nil
214+
}
215+
// dump whatever already exists in the datadir
216+
stack, _ := makeConfigNode(ctx)
217+
for _, name := range []string{"chaindata", "lightchaindata"} {
218+
db, err := stack.OpenDatabase(name, 0, 0, "", true)
219+
if err != nil {
220+
if !os.IsNotExist(err) {
221+
return err
222+
}
223+
continue
224+
}
225+
genesis, err := core.ReadGenesis(db)
226+
if err != nil {
227+
utils.Fatalf("failed to read genesis: %s", err)
228+
}
229+
db.Close()
230+
231+
if err := json.NewEncoder(os.Stdout).Encode(*genesis); err != nil {
232+
utils.Fatalf("could not encode stored genesis: %s", err)
233+
}
234+
return nil
210235
}
211-
if err := json.NewEncoder(os.Stdout).Encode(genesis); err != nil {
212-
utils.Fatalf("could not encode genesis")
236+
if ctx.IsSet(utils.DataDirFlag.Name) {
237+
utils.Fatalf("no existing datadir at %s", stack.Config().DataDir)
213238
}
239+
utils.Fatalf("no network preset provided. no exisiting genesis in the default datadir")
214240
return nil
215241
}
216242

cmd/utils/flags.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -988,9 +988,7 @@ var (
988988
KilnFlag,
989989
}
990990
// NetworkFlags is the flag group of all built-in supported networks.
991-
NetworkFlags = append([]cli.Flag{
992-
MainnetFlag,
993-
}, TestnetFlags...)
991+
NetworkFlags = append([]cli.Flag{MainnetFlag}, TestnetFlags...)
994992

995993
// DatabasePathFlags is the flag group of all database path flags.
996994
DatabasePathFlags = []cli.Flag{
@@ -2140,6 +2138,16 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.
21402138
return chainDb
21412139
}
21422140

2141+
func IsNetworkPreset(ctx *cli.Context) bool {
2142+
for _, flag := range NetworkFlags {
2143+
bFlag, _ := flag.(*cli.BoolFlag)
2144+
if ctx.IsSet(bFlag.Name) {
2145+
return true
2146+
}
2147+
}
2148+
return false
2149+
}
2150+
21432151
func MakeGenesis(ctx *cli.Context) *core.Genesis {
21442152
var genesis *core.Genesis
21452153
switch {

core/genesis.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,41 @@ type Genesis struct {
6565
BaseFee *big.Int `json:"baseFeePerGas"`
6666
}
6767

68+
func ReadGenesis(db ethdb.Database) (*Genesis, error) {
69+
var genesis Genesis
70+
stored := rawdb.ReadCanonicalHash(db, 0)
71+
if (stored == common.Hash{}) {
72+
return nil, fmt.Errorf("invalid genesis hash in database: %x", stored)
73+
}
74+
blob := rawdb.ReadGenesisStateSpec(db, stored)
75+
if blob == nil {
76+
return nil, fmt.Errorf("genesis state missing from db")
77+
}
78+
if len(blob) != 0 {
79+
if err := genesis.Alloc.UnmarshalJSON(blob); err != nil {
80+
return nil, fmt.Errorf("could not unmarshal genesis state json: %s", err)
81+
}
82+
}
83+
genesis.Config = rawdb.ReadChainConfig(db, stored)
84+
if genesis.Config == nil {
85+
return nil, fmt.Errorf("genesis config missing from db")
86+
}
87+
genesisBlock := rawdb.ReadBlock(db, stored, 0)
88+
if genesisBlock == nil {
89+
return nil, fmt.Errorf("genesis block missing from db")
90+
}
91+
genesisHeader := genesisBlock.Header()
92+
genesis.Nonce = genesisHeader.Nonce.Uint64()
93+
genesis.Timestamp = genesisHeader.Time
94+
genesis.ExtraData = genesisHeader.Extra
95+
genesis.GasLimit = genesisHeader.GasLimit
96+
genesis.Difficulty = genesisHeader.Difficulty
97+
genesis.Mixhash = genesisHeader.MixDigest
98+
genesis.Coinbase = genesisHeader.Coinbase
99+
100+
return &genesis, nil
101+
}
102+
68103
// GenesisAlloc specifies the initial state that is part of the genesis block.
69104
type GenesisAlloc map[common.Address]GenesisAccount
70105

0 commit comments

Comments
 (0)