github.com/noirx94/tendermintmp@v0.0.1/test/maverick/main.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  
     8  	"github.com/spf13/cobra"
     9  	"github.com/spf13/viper"
    10  
    11  	cmd "github.com/tendermint/tendermint/cmd/tendermint/commands"
    12  	"github.com/tendermint/tendermint/cmd/tendermint/commands/debug"
    13  	cfg "github.com/tendermint/tendermint/config"
    14  	"github.com/tendermint/tendermint/libs/cli"
    15  	tmflags "github.com/tendermint/tendermint/libs/cli/flags"
    16  	"github.com/tendermint/tendermint/libs/log"
    17  	tmos "github.com/tendermint/tendermint/libs/os"
    18  	tmrand "github.com/tendermint/tendermint/libs/rand"
    19  	"github.com/tendermint/tendermint/p2p"
    20  	cs "github.com/tendermint/tendermint/test/maverick/consensus"
    21  	nd "github.com/tendermint/tendermint/test/maverick/node"
    22  	"github.com/tendermint/tendermint/types"
    23  	tmtime "github.com/tendermint/tendermint/types/time"
    24  )
    25  
    26  var (
    27  	config          = cfg.DefaultConfig()
    28  	logger          = log.NewTMLogger(log.NewSyncWriter(os.Stdout))
    29  	misbehaviorFlag = ""
    30  )
    31  
    32  func init() {
    33  	registerFlagsRootCmd(RootCmd)
    34  }
    35  
    36  func registerFlagsRootCmd(command *cobra.Command) {
    37  	command.PersistentFlags().String("log_level", config.LogLevel, "Log level")
    38  }
    39  
    40  func ParseConfig() (*cfg.Config, error) {
    41  	conf := cfg.DefaultConfig()
    42  	err := viper.Unmarshal(conf)
    43  	if err != nil {
    44  		return nil, err
    45  	}
    46  	conf.SetRoot(conf.RootDir)
    47  	cfg.EnsureRoot(conf.RootDir)
    48  	if err = conf.ValidateBasic(); err != nil {
    49  		return nil, fmt.Errorf("error in config file: %v", err)
    50  	}
    51  	return conf, err
    52  }
    53  
    54  // RootCmd is the root command for Tendermint core.
    55  var RootCmd = &cobra.Command{
    56  	Use:   "maverick",
    57  	Short: "Tendermint Maverick Node",
    58  	Long: "Tendermint Maverick Node for testing with faulty consensus misbehaviors in a testnet. Contains " +
    59  		"all the functionality of a normal node but custom misbehaviors can be injected when running the node " +
    60  		"through a flag. See maverick node --help for how the misbehavior flag is constructured",
    61  	PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) {
    62  		fmt.Printf("use: %v, args: %v", cmd.Use, cmd.Args)
    63  
    64  		config, err = ParseConfig()
    65  		if err != nil {
    66  			return err
    67  		}
    68  
    69  		if config.LogFormat == cfg.LogFormatJSON {
    70  			logger = log.NewTMJSONLogger(log.NewSyncWriter(os.Stdout))
    71  		}
    72  
    73  		logger, err = tmflags.ParseLogLevel(config.LogLevel, logger, cfg.DefaultLogLevel)
    74  		if err != nil {
    75  			return err
    76  		}
    77  
    78  		if viper.GetBool(cli.TraceFlag) {
    79  			logger = log.NewTracingLogger(logger)
    80  		}
    81  
    82  		logger = logger.With("module", "main")
    83  		return nil
    84  	},
    85  }
    86  
    87  func main() {
    88  	rootCmd := RootCmd
    89  	rootCmd.AddCommand(
    90  		ListMisbehaviorCmd,
    91  		cmd.GenValidatorCmd,
    92  		InitFilesCmd,
    93  		cmd.ProbeUpnpCmd,
    94  		cmd.ReplayCmd,
    95  		cmd.ReplayConsoleCmd,
    96  		cmd.ResetAllCmd,
    97  		cmd.ResetPrivValidatorCmd,
    98  		cmd.ShowValidatorCmd,
    99  		cmd.ShowNodeIDCmd,
   100  		cmd.GenNodeKeyCmd,
   101  		cmd.VersionCmd,
   102  		debug.DebugCmd,
   103  		cli.NewCompletionCmd(rootCmd, true),
   104  	)
   105  
   106  	nodeCmd := &cobra.Command{
   107  		Use:   "node",
   108  		Short: "Run the maverick node",
   109  		RunE: func(command *cobra.Command, args []string) error {
   110  			return startNode(config, logger, misbehaviorFlag)
   111  		},
   112  	}
   113  
   114  	cmd.AddNodeFlags(nodeCmd)
   115  
   116  	// Create & start node
   117  	rootCmd.AddCommand(nodeCmd)
   118  
   119  	// add special flag for misbehaviors
   120  	nodeCmd.Flags().StringVar(
   121  		&misbehaviorFlag,
   122  		"misbehaviors",
   123  		"",
   124  		"Select the misbehaviors of the node (comma-separated, no spaces in between): \n"+
   125  			"e.g. --misbehaviors double-prevote,3\n"+
   126  			"You can also have multiple misbehaviors: e.g. double-prevote,3,no-vote,5")
   127  
   128  	cmd := cli.PrepareBaseCmd(rootCmd, "TM", os.ExpandEnv(filepath.Join("$HOME", cfg.DefaultTendermintDir)))
   129  	if err := cmd.Execute(); err != nil {
   130  		panic(err)
   131  	}
   132  }
   133  
   134  func startNode(config *cfg.Config, logger log.Logger, misbehaviorFlag string) error {
   135  	misbehaviors, err := nd.ParseMisbehaviors(misbehaviorFlag)
   136  	if err != nil {
   137  		return err
   138  	}
   139  
   140  	node, err := nd.DefaultNewNode(config, logger, misbehaviors)
   141  	if err != nil {
   142  		return fmt.Errorf("failed to create node: %w", err)
   143  	}
   144  
   145  	if err := node.Start(); err != nil {
   146  		return fmt.Errorf("failed to start node: %w", err)
   147  	}
   148  
   149  	logger.Info("Started node", "nodeInfo", node.Switch().NodeInfo())
   150  
   151  	// Stop upon receiving SIGTERM or CTRL-C.
   152  	tmos.TrapSignal(logger, func() {
   153  		if node.IsRunning() {
   154  			if err := node.Stop(); err != nil {
   155  				logger.Error("unable to stop the node", "error", err)
   156  			}
   157  		}
   158  	})
   159  
   160  	// Run forever.
   161  	select {}
   162  }
   163  
   164  var InitFilesCmd = &cobra.Command{
   165  	Use:   "init",
   166  	Short: "Initialize Tendermint",
   167  	RunE:  initFiles,
   168  }
   169  
   170  func initFiles(cmd *cobra.Command, args []string) error {
   171  	return initFilesWithConfig(config)
   172  }
   173  
   174  func initFilesWithConfig(config *cfg.Config) error {
   175  	// private validator
   176  	privValKeyFile := config.PrivValidatorKeyFile()
   177  	privValStateFile := config.PrivValidatorStateFile()
   178  	var pv *nd.FilePV
   179  	if tmos.FileExists(privValKeyFile) {
   180  		pv = nd.LoadFilePV(privValKeyFile, privValStateFile)
   181  		logger.Info("Found private validator", "keyFile", privValKeyFile,
   182  			"stateFile", privValStateFile)
   183  	} else {
   184  		pv = nd.GenFilePV(privValKeyFile, privValStateFile)
   185  		pv.Save()
   186  		logger.Info("Generated private validator", "keyFile", privValKeyFile,
   187  			"stateFile", privValStateFile)
   188  	}
   189  
   190  	nodeKeyFile := config.NodeKeyFile()
   191  	if tmos.FileExists(nodeKeyFile) {
   192  		logger.Info("Found node key", "path", nodeKeyFile)
   193  	} else {
   194  		if _, err := p2p.LoadOrGenNodeKey(nodeKeyFile); err != nil {
   195  			return err
   196  		}
   197  		logger.Info("Generated node key", "path", nodeKeyFile)
   198  	}
   199  
   200  	// genesis file
   201  	genFile := config.GenesisFile()
   202  	if tmos.FileExists(genFile) {
   203  		logger.Info("Found genesis file", "path", genFile)
   204  	} else {
   205  		genDoc := types.GenesisDoc{
   206  			ChainID:         fmt.Sprintf("test-chain-%v", tmrand.Str(6)),
   207  			GenesisTime:     tmtime.Now(),
   208  			ConsensusParams: types.DefaultConsensusParams(),
   209  		}
   210  		pubKey, err := pv.GetPubKey()
   211  		if err != nil {
   212  			return fmt.Errorf("can't get pubkey: %w", err)
   213  		}
   214  		genDoc.Validators = []types.GenesisValidator{{
   215  			Address: pubKey.Address(),
   216  			PubKey:  pubKey,
   217  			Power:   10,
   218  		}}
   219  
   220  		if err := genDoc.SaveAs(genFile); err != nil {
   221  			return err
   222  		}
   223  		logger.Info("Generated genesis file", "path", genFile)
   224  	}
   225  
   226  	return nil
   227  }
   228  
   229  var ListMisbehaviorCmd = &cobra.Command{
   230  	Use:   "misbehaviors",
   231  	Short: "Lists possible misbehaviors",
   232  	RunE:  listMisbehaviors,
   233  }
   234  
   235  func listMisbehaviors(cmd *cobra.Command, args []string) error {
   236  	str := "Currently registered misbehaviors: \n"
   237  	for key := range cs.MisbehaviorList {
   238  		str += fmt.Sprintf("- %s\n", key)
   239  	}
   240  	fmt.Println(str)
   241  	return nil
   242  }