github.com/line/ostracon@v1.0.10-0.20230328032236-7f20145f065d/tools/tm-signer-harness/main.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"time"
    10  
    11  	"github.com/line/ostracon/crypto/ed25519"
    12  	"github.com/line/ostracon/libs/log"
    13  	"github.com/line/ostracon/privval"
    14  	"github.com/line/ostracon/tools/tm-signer-harness/internal"
    15  	"github.com/line/ostracon/version"
    16  )
    17  
    18  const (
    19  	defaultAcceptRetries    = 100
    20  	defaultBindAddr         = "tcp://127.0.0.1:0"
    21  	defaultOCHome           = "~/.ostracon"
    22  	defaultAcceptDeadline   = 1
    23  	defaultConnDeadline     = 3
    24  	defaultExtractKeyOutput = "./signing.key"
    25  )
    26  
    27  var logger = log.NewOCLogger(log.NewSyncWriter(os.Stdout))
    28  
    29  // Command line flags
    30  var (
    31  	flagAcceptRetries int
    32  	flagBindAddr      string
    33  	flagOCHome        string
    34  	flagKeyOutputPath string
    35  )
    36  
    37  // Command line commands
    38  var (
    39  	rootCmd       *flag.FlagSet
    40  	runCmd        *flag.FlagSet
    41  	extractKeyCmd *flag.FlagSet
    42  	versionCmd    *flag.FlagSet
    43  )
    44  
    45  func init() {
    46  	rootCmd = flag.NewFlagSet("root", flag.ExitOnError)
    47  	rootCmd.Usage = func() {
    48  		fmt.Println(`Remote signer test harness for Ostracon.
    49  
    50  Usage:
    51    tm-signer-harness <command> [flags]
    52  
    53  Available Commands:
    54    extract_key        Extracts a signing key from a local Ostracon instance
    55    help               Help on the available commands
    56    run                Runs the test harness
    57    version            Display version information and exit
    58  
    59  Use "tm-signer-harness help <command>" for more information about that command.`)
    60  		fmt.Println("")
    61  	}
    62  
    63  	runCmd = flag.NewFlagSet("run", flag.ExitOnError)
    64  	runCmd.IntVar(&flagAcceptRetries,
    65  		"accept-retries",
    66  		defaultAcceptRetries,
    67  		"The number of attempts to listen for incoming connections")
    68  	runCmd.StringVar(&flagBindAddr, "addr", defaultBindAddr, "Bind to this address for the testing")
    69  	runCmd.StringVar(&flagOCHome, "ochome", defaultOCHome, "Path to the Ostracon home directory")
    70  	runCmd.Usage = func() {
    71  		fmt.Println(`Runs the remote signer test harness for Ostracon.
    72  
    73  Usage:
    74    tm-signer-harness run [flags]
    75  
    76  Flags:`)
    77  		runCmd.PrintDefaults()
    78  		fmt.Println("")
    79  	}
    80  
    81  	extractKeyCmd = flag.NewFlagSet("extract_key", flag.ExitOnError)
    82  	extractKeyCmd.StringVar(&flagKeyOutputPath,
    83  		"output",
    84  		defaultExtractKeyOutput,
    85  		"Path to which signing key should be written")
    86  	extractKeyCmd.StringVar(&flagOCHome, "ochome", defaultOCHome, "Path to the Ostracon home directory")
    87  	extractKeyCmd.Usage = func() {
    88  		fmt.Println(`Extracts a signing key from a local Ostracon instance for use in the remote
    89  signer under test.
    90  
    91  Usage:
    92    tm-signer-harness extract_key [flags]
    93  
    94  Flags:`)
    95  		extractKeyCmd.PrintDefaults()
    96  		fmt.Println("")
    97  	}
    98  
    99  	versionCmd = flag.NewFlagSet("version", flag.ExitOnError)
   100  	versionCmd.Usage = func() {
   101  		fmt.Println(`
   102  Prints the Ostracon version for which this remote signer harness was built.
   103  
   104  Usage:
   105    tm-signer-harness version`)
   106  		fmt.Println("")
   107  	}
   108  }
   109  
   110  func runTestHarness(acceptRetries int, bindAddr, ochome string) {
   111  	ochome = internal.ExpandPath(ochome)
   112  	cfg := internal.TestHarnessConfig{
   113  		BindAddr:         bindAddr,
   114  		KeyFile:          filepath.Join(ochome, "config", "priv_validator_key.json"),
   115  		StateFile:        filepath.Join(ochome, "data", "priv_validator_state.json"),
   116  		GenesisFile:      filepath.Join(ochome, "config", "genesis.json"),
   117  		AcceptDeadline:   time.Duration(defaultAcceptDeadline) * time.Second,
   118  		AcceptRetries:    acceptRetries,
   119  		ConnDeadline:     time.Duration(defaultConnDeadline) * time.Second,
   120  		SecretConnKey:    ed25519.GenPrivKey(),
   121  		ExitWhenComplete: true,
   122  	}
   123  	harness, err := internal.NewTestHarness(logger, cfg)
   124  	if err != nil {
   125  		logger.Error(err.Error())
   126  		if therr, ok := err.(*internal.TestHarnessError); ok {
   127  			os.Exit(therr.Code)
   128  		}
   129  		os.Exit(internal.ErrOther)
   130  	}
   131  	harness.Run()
   132  }
   133  
   134  func extractKey(ochome, outputPath string) {
   135  	keyFile := filepath.Join(internal.ExpandPath(ochome), "config", "priv_validator_key.json")
   136  	stateFile := filepath.Join(internal.ExpandPath(ochome), "data", "priv_validator_state.json")
   137  	fpv := privval.LoadFilePV(keyFile, stateFile)
   138  	pkb := []byte(fpv.Key.PrivKey.(ed25519.PrivKey))
   139  	if err := ioutil.WriteFile(internal.ExpandPath(outputPath), pkb[:32], 0600); err != nil {
   140  		logger.Info("Failed to write private key", "output", outputPath, "err", err)
   141  		os.Exit(1)
   142  	}
   143  	logger.Info("Successfully wrote private key", "output", outputPath)
   144  }
   145  
   146  func main() {
   147  	if err := rootCmd.Parse(os.Args[1:]); err != nil {
   148  		fmt.Printf("Error parsing flags: %v\n", err)
   149  		os.Exit(1)
   150  	}
   151  	if rootCmd.NArg() == 0 || (rootCmd.NArg() == 1 && rootCmd.Arg(0) == "help") {
   152  		rootCmd.Usage()
   153  		os.Exit(0)
   154  	}
   155  
   156  	logger = log.NewFilter(logger, log.AllowInfo())
   157  
   158  	switch rootCmd.Arg(0) {
   159  	case "help":
   160  		switch rootCmd.Arg(1) {
   161  		case "run":
   162  			runCmd.Usage()
   163  		case "extract_key":
   164  			extractKeyCmd.Usage()
   165  		case "version":
   166  			versionCmd.Usage()
   167  		default:
   168  			fmt.Printf("Unrecognized command: %s\n", rootCmd.Arg(1))
   169  			os.Exit(1)
   170  		}
   171  	case "run":
   172  		if err := runCmd.Parse(os.Args[2:]); err != nil {
   173  			fmt.Printf("Error parsing flags: %v\n", err)
   174  			os.Exit(1)
   175  		}
   176  		runTestHarness(flagAcceptRetries, flagBindAddr, flagOCHome)
   177  	case "extract_key":
   178  		if err := extractKeyCmd.Parse(os.Args[2:]); err != nil {
   179  			fmt.Printf("Error parsing flags: %v\n", err)
   180  			os.Exit(1)
   181  		}
   182  		extractKey(flagOCHome, flagKeyOutputPath)
   183  	case "version":
   184  		fmt.Println(version.OCCoreSemVer)
   185  	default:
   186  		fmt.Printf("Unrecognized command: %s\n", flag.Arg(0))
   187  		os.Exit(1)
   188  	}
   189  }