From 9caf94fad841d95bb669184e7591a914956b8603 Mon Sep 17 00:00:00 2001 From: YoshihitoAso Date: Wed, 13 Mar 2024 16:46:45 +0900 Subject: [PATCH] geth: add new update transitions helper utility --- cmd/geth/chaincmd.go | 71 ++++++++++++++++++++++++++++++++++++++++++++ cmd/geth/main.go | 1 + 2 files changed, 72 insertions(+) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index db29a87e9..d17c8e923 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -21,6 +21,7 @@ import ( "fmt" "io" "os" + "reflect" "runtime" "strconv" "sync/atomic" @@ -73,6 +74,19 @@ It expects the genesis file as argument.`, Category: "BLOCKCHAIN COMMANDS", Description: ` The dumpgenesis command dumps the genesis block configuration in JSON format to stdout.`, + } + updateCommand = cli.Command{ + Action: utils.MigrateFlags(updateTransitions), + Name: "update", + Usage: "Update genesis block with new transitions", + ArgsUsage: "", + Flags: []cli.Flag{ + utils.DataDirFlag, + }, + Category: "BLOCKCHAIN COMMANDS", + Description: ` +The update commands updates the chain data configuration in genesis block for new transition changes. +It expects the genesis file as argument.`, } importCommand = cli.Command{ Action: utils.MigrateFlags(importChain), @@ -206,6 +220,63 @@ func getIsQuorum(file io.Reader) bool { return altGenesis.Config.IsQuorum == nil || *altGenesis.Config.IsQuorum } +// updateTransitions will update genesis block with the new transitions data +func updateTransitions(ctx *cli.Context) error { + // Open and initialise both full and light databases + stack, _ := makeConfigNode(ctx) + defer stack.Close() + + // Make sure we have a valid genesis JSON + genesisPath := ctx.Args().First() + if len(genesisPath) == 0 { + utils.Fatalf("Must supply path to genesis JSON file") + } + file, err := os.Open(genesisPath) + if err != nil { + utils.Fatalf("Failed to read genesis file: %v", err) + } + defer file.Close() + + genesis := new(core.Genesis) + if err := json.NewDecoder(file).Decode(genesis); err != nil { + utils.Fatalf("invalid genesis file: %v", err) + } + + // Transitions updates only applies to Quorum + file.Seek(0, 0) + genesis.Config.IsQuorum = getIsQuorum(file) + if genesis.Config.IsQuorum { + err = genesis.Config.CheckTransitionsData() + if err != nil { + utils.Fatalf("Transitions data invalid: %v", err) + } + } else { + return fmt.Errorf("update transitions only apply to quorum configuration") + } + + // Update transitions and recommit to db + for _, name := range []string{"chaindata", "lightchaindata"} { + chaindb, err := stack.OpenDatabase(name, 0, 0, "", false) + if err != nil { + utils.Fatalf("Failed to open database: %v", err) + } + stored := rawdb.ReadCanonicalHash(chaindb, 0) + storedcfg := rawdb.ReadChainConfig(chaindb, stored) + if storedcfg == nil { + return fmt.Errorf("found genesis block without chain config") + } + // Check that new transitions have changed before updating them + if !reflect.DeepEqual(storedcfg.Transitions, genesis.Config.Transitions) { + log.Info("Change found in transitions, proceeding to update chain config") + storedcfg.Transitions = genesis.Config.Transitions + rawdb.WriteChainConfig(chaindb, stored, storedcfg) + } else { + log.Info("No change in transitions, no update required to chain config") + } + } + return nil +} + // initGenesis will initialise the given JSON format genesis file and writes it as // the zero'd block (i.e. genesis) or will fail hard if it can't succeed. func initGenesis(ctx *cli.Context) error { diff --git a/cmd/geth/main.go b/cmd/geth/main.go index f7a65e3e4..003124a5a 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -269,6 +269,7 @@ func init() { app.Commands = []cli.Command{ // See chaincmd.go: initCommand, + updateCommand, mpsdbUpgradeCommand, importCommand, exportCommand,