cli: simplify resetting commands (#8312)

This commit is contained in:
Callum Waters
2022-04-14 12:27:08 +12:00
committed by GitHub
parent 6bbf5b6d0f
commit 68c9efdb82
6 changed files with 162 additions and 69 deletions

View File

@@ -13,81 +13,92 @@ import (
"github.com/tendermint/tendermint/types"
)
// MakeResetAllCommand constructs a command that removes the database of
// MakeResetCommand constructs a command that removes the database of
// the specified Tendermint core instance.
func MakeResetAllCommand(conf *config.Config, logger log.Logger) *cobra.Command {
func MakeResetCommand(conf *config.Config, logger log.Logger) *cobra.Command {
var keyType string
cmd := &cobra.Command{
Use: "unsafe-reset-all",
Short: "(unsafe) Remove all the data and WAL, reset this node's validator to genesis state",
resetCmd := &cobra.Command{
Use: "reset",
Short: "Set of commands to conveniently reset tendermint related data",
}
resetBlocksCmd := &cobra.Command{
Use: "blockchain",
Short: "Removes all blocks, state, transactions and evidence stored by the tendermint node",
RunE: func(cmd *cobra.Command, args []string) error {
return resetAll(conf.DBDir(), conf.PrivValidator.KeyFile(),
return ResetState(conf.DBDir(), logger)
},
}
resetPeersCmd := &cobra.Command{
Use: "peers",
Short: "Removes all peer addresses",
RunE: func(cmd *cobra.Command, args []string) error {
return ResetPeerStore(conf.DBDir())
},
}
resetSignerCmd := &cobra.Command{
Use: "unsafe-signer",
Short: "esets private validator signer state",
Long: `Resets private validator signer state.
Only use in testing. This can cause the node to double sign`,
RunE: func(cmd *cobra.Command, args []string) error {
return ResetFilePV(conf.PrivValidator.KeyFile(), conf.PrivValidator.StateFile(), logger, keyType)
},
}
resetAllCmd := &cobra.Command{
Use: "unsafe-all",
Short: "Removes all tendermint data including signing state",
Long: `Removes all tendermint data including signing state.
Only use in testing. This can cause the node to double sign`,
RunE: func(cmd *cobra.Command, args []string) error {
return ResetAll(conf.DBDir(), conf.PrivValidator.KeyFile(),
conf.PrivValidator.StateFile(), logger, keyType)
},
}
cmd.Flags().StringVar(&keyType, "key", types.ABCIPubKeyTypeEd25519,
"Key type to generate privval file with. Options: ed25519, secp256k1")
return cmd
resetSignerCmd.Flags().StringVar(&keyType, "key", types.ABCIPubKeyTypeEd25519,
"Signer key type. Options: ed25519, secp256k1")
resetAllCmd.Flags().StringVar(&keyType, "key", types.ABCIPubKeyTypeEd25519,
"Signer key type. Options: ed25519, secp256k1")
resetCmd.AddCommand(resetBlocksCmd)
resetCmd.AddCommand(resetPeersCmd)
resetCmd.AddCommand(resetSignerCmd)
resetCmd.AddCommand(resetAllCmd)
return resetCmd
}
// MakeResetStateCommand constructs a command that removes the database of
// the specified Tendermint core instance.
func MakeResetStateCommand(conf *config.Config, logger log.Logger) *cobra.Command {
var keyType string
return &cobra.Command{
Use: "reset-state",
Short: "Remove all the data and WAL",
RunE: func(cmd *cobra.Command, args []string) error {
return resetState(conf.DBDir(), logger, keyType)
},
}
}
func MakeResetPrivateValidatorCommand(conf *config.Config, logger log.Logger) *cobra.Command {
var keyType string
cmd := &cobra.Command{
Use: "unsafe-reset-priv-validator",
Short: "(unsafe) Reset this node's validator to genesis state",
RunE: func(cmd *cobra.Command, args []string) error {
return resetFilePV(conf.PrivValidator.KeyFile(), conf.PrivValidator.StateFile(), logger, keyType)
},
}
cmd.Flags().StringVar(&keyType, "key", types.ABCIPubKeyTypeEd25519,
"Key type to generate privval file with. Options: ed25519, secp256k1")
return cmd
}
// XXX: this is totally unsafe.
// it's only suitable for testnets.
// XXX: this is totally unsafe.
// it's only suitable for testnets.
// resetAll removes address book files plus all data, and resets the privValdiator data.
func resetAll(dbDir, privValKeyFile, privValStateFile string, logger log.Logger, keyType string) error {
// ResetAll removes address book files plus all data, and resets the privValdiator data.
// Exported for extenal CLI usage
// XXX: this is unsafe and should only suitable for testnets.
func ResetAll(dbDir, privValKeyFile, privValStateFile string, logger log.Logger, keyType string) error {
if err := os.RemoveAll(dbDir); err == nil {
logger.Info("Removed all blockchain history", "dir", dbDir)
} else {
logger.Error("error removing all blockchain history", "dir", dbDir, "err", err)
}
return resetFilePV(privValKeyFile, privValStateFile, logger, keyType)
if err := tmos.EnsureDir(dbDir, 0700); err != nil {
logger.Error("unable to recreate dbDir", "err", err)
}
// recreate the dbDir since the privVal state needs to live there
return ResetFilePV(privValKeyFile, privValStateFile, logger, keyType)
}
// resetState removes address book files plus all databases.
func resetState(dbDir string, logger log.Logger, keyType string) error {
// ResetState removes all blocks, tendermint state, indexed transactions and evidence.
func ResetState(dbDir string, logger log.Logger) error {
blockdb := filepath.Join(dbDir, "blockstore.db")
state := filepath.Join(dbDir, "state.db")
wal := filepath.Join(dbDir, "cs.wal")
evidence := filepath.Join(dbDir, "evidence.db")
txIndex := filepath.Join(dbDir, "tx_index.db")
peerstore := filepath.Join(dbDir, "peerstore.db")
if tmos.FileExists(blockdb) {
if err := os.RemoveAll(blockdb); err == nil {
@@ -129,20 +140,13 @@ func resetState(dbDir string, logger log.Logger, keyType string) error {
}
}
if tmos.FileExists(peerstore) {
if err := os.RemoveAll(peerstore); err == nil {
logger.Info("Removed peerstore.db", "dir", peerstore)
} else {
logger.Error("error removing peerstore.db", "dir", peerstore, "err", err)
}
}
if err := tmos.EnsureDir(dbDir, 0700); err != nil {
logger.Error("unable to recreate dbDir", "err", err)
}
return nil
return tmos.EnsureDir(dbDir, 0700)
}
func resetFilePV(privValKeyFile, privValStateFile string, logger log.Logger, keyType string) error {
// ResetFilePV loads the file private validator and resets the watermark to 0. If used on an existing network,
// this can cause the node to double sign.
// XXX: this is unsafe and should only suitable for testnets.
func ResetFilePV(privValKeyFile, privValStateFile string, logger log.Logger, keyType string) error {
if _, err := os.Stat(privValKeyFile); err == nil {
pv, err := privval.LoadFilePVEmptyState(privValKeyFile, privValStateFile)
if err != nil {
@@ -166,3 +170,13 @@ func resetFilePV(privValKeyFile, privValStateFile string, logger log.Logger, key
}
return nil
}
// ResetPeerStore removes the peer store containing all information used by the tendermint networking layer
// In the case of a reset, new peers will need to be set either via the config or through the discovery mechanism
func ResetPeerStore(dbDir string) error {
peerstore := filepath.Join(dbDir, "peerstore.db")
if tmos.FileExists(peerstore) {
return os.RemoveAll(peerstore)
}
return nil
}

View File

@@ -0,0 +1,62 @@
package commands
import (
"context"
"path/filepath"
"testing"
"github.com/stretchr/testify/require"
cfg "github.com/tendermint/tendermint/config"
"github.com/tendermint/tendermint/libs/log"
"github.com/tendermint/tendermint/privval"
"github.com/tendermint/tendermint/types"
)
func Test_ResetAll(t *testing.T) {
config := cfg.TestConfig()
dir := t.TempDir()
config.SetRoot(dir)
logger := log.NewNopLogger()
cfg.EnsureRoot(dir)
require.NoError(t, initFilesWithConfig(context.Background(), config, logger, types.ABCIPubKeyTypeEd25519))
pv, err := privval.LoadFilePV(config.PrivValidator.KeyFile(), config.PrivValidator.StateFile())
require.NoError(t, err)
pv.LastSignState.Height = 10
require.NoError(t, pv.Save())
require.NoError(t, ResetAll(config.DBDir(), config.PrivValidator.KeyFile(),
config.PrivValidator.StateFile(), logger, types.ABCIPubKeyTypeEd25519))
require.DirExists(t, config.DBDir())
require.NoFileExists(t, filepath.Join(config.DBDir(), "block.db"))
require.NoFileExists(t, filepath.Join(config.DBDir(), "state.db"))
require.NoFileExists(t, filepath.Join(config.DBDir(), "evidence.db"))
require.NoFileExists(t, filepath.Join(config.DBDir(), "tx_index.db"))
require.FileExists(t, config.PrivValidator.StateFile())
pv, err = privval.LoadFilePV(config.PrivValidator.KeyFile(), config.PrivValidator.StateFile())
require.NoError(t, err)
require.Equal(t, int64(0), pv.LastSignState.Height)
}
func Test_ResetState(t *testing.T) {
config := cfg.TestConfig()
dir := t.TempDir()
config.SetRoot(dir)
logger := log.NewNopLogger()
cfg.EnsureRoot(dir)
require.NoError(t, initFilesWithConfig(context.Background(), config, logger, types.ABCIPubKeyTypeEd25519))
pv, err := privval.LoadFilePV(config.PrivValidator.KeyFile(), config.PrivValidator.StateFile())
require.NoError(t, err)
pv.LastSignState.Height = 10
require.NoError(t, pv.Save())
require.NoError(t, ResetState(config.DBDir(), logger))
require.DirExists(t, config.DBDir())
require.NoFileExists(t, filepath.Join(config.DBDir(), "block.db"))
require.NoFileExists(t, filepath.Join(config.DBDir(), "state.db"))
require.NoFileExists(t, filepath.Join(config.DBDir(), "evidence.db"))
require.NoFileExists(t, filepath.Join(config.DBDir(), "tx_index.db"))
require.FileExists(t, config.PrivValidator.StateFile())
pv, err = privval.LoadFilePV(config.PrivValidator.KeyFile(), config.PrivValidator.StateFile())
require.NoError(t, err)
// private validator state should still be in tact.
require.Equal(t, int64(10), pv.LastSignState.Height)
}

View File

@@ -33,9 +33,7 @@ func main() {
commands.MakeLightCommand(conf, logger),
commands.MakeReplayCommand(conf, logger),
commands.MakeReplayConsoleCommand(conf, logger),
commands.MakeResetAllCommand(conf, logger),
commands.MakeResetStateCommand(conf, logger),
commands.MakeResetPrivateValidatorCommand(conf, logger),
commands.MakeResetCommand(conf, logger),
commands.MakeShowValidatorCommand(conf, logger),
commands.MakeTestnetFilesCommand(conf, logger),
commands.MakeShowNodeIDCommand(conf),