github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/cmd/u2u/launcher/validatorcmd.go (about)

     1  package launcher
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	"crypto/rand"
     6  	"fmt"
     7  	"path"
     8  	"strings"
     9  	
    10  	"gopkg.in/urfave/cli.v1"
    11  
    12  	"github.com/unicornultrafoundation/go-u2u/cmd/utils"
    13  	"github.com/unicornultrafoundation/go-u2u/common"
    14  	"github.com/unicornultrafoundation/go-u2u/crypto"
    15  	"github.com/unicornultrafoundation/go-u2u/native/validatorpk"
    16  	"github.com/unicornultrafoundation/go-u2u/valkeystore"
    17  	"github.com/unicornultrafoundation/go-u2u/valkeystore/encryption"
    18  )
    19  
    20  var (
    21  	validatorCommand = cli.Command{
    22  		Name:     "validator",
    23  		Usage:    "Manage validators",
    24  		Category: "VALIDATOR COMMANDS",
    25  		Description: `
    26  
    27  Create a new validator private key.
    28  
    29  It supports interactive mode, when you are prompted for password as well as
    30  non-interactive mode where passwords are supplied via a given password file.
    31  Non-interactive mode is only meant for scripted use on test networks or known
    32  safe environments.
    33  
    34  Make sure you remember the password you gave when creating a new validator key.
    35  Without it you are not able to unlock your validator key.
    36  
    37  Note that exporting your key in unencrypted format is NOT supported.
    38  
    39  Keys are stored under <DATADIR>/keystore/validator.
    40  It is safe to transfer the entire directory or the individual keys therein
    41  between u2u nodes by simply copying.
    42  
    43  Make sure you backup your keys regularly.`,
    44  		Subcommands: []cli.Command{
    45  			{
    46  				Name:   "new",
    47  				Usage:  "Create a new validator key",
    48  				Action: utils.MigrateFlags(validatorKeyCreate),
    49  				Flags: []cli.Flag{
    50  					DataDirFlag,
    51  					utils.KeyStoreDirFlag,
    52  					utils.PasswordFileFlag,
    53  				},
    54  				Description: `
    55      u2u validator new
    56  
    57  Creates a new validator private key and prints the public key.
    58  
    59  The key is saved in encrypted format, you are prompted for a passphrase.
    60  
    61  You must remember this passphrase to unlock your key in the future.
    62  
    63  For non-interactive use the passphrase can be specified with the --validator.password flag:
    64  
    65  Note, this is meant to be used for testing only, it is a bad idea to save your
    66  password to file or expose in any other way.
    67  `,
    68  			},
    69  			{
    70  				Name:   "convert",
    71  				Usage:  "Convert an account key to a validator key",
    72  				Action: utils.MigrateFlags(validatorKeyConvert),
    73  				Flags: []cli.Flag{
    74  					DataDirFlag,
    75  					utils.KeyStoreDirFlag,
    76  				},
    77  				ArgsUsage: "<account address> <validator pubkey>",
    78  				Description: `
    79      u2u validator convert
    80  
    81  Converts an account private key to a validator private key and saves in the validator keystore.
    82  `,
    83  			},
    84  		},
    85  	}
    86  )
    87  
    88  // validatorKeyCreate creates a new validator key into the keystore defined by the CLI flags.
    89  func validatorKeyCreate(ctx *cli.Context) error {
    90  	cfg := makeAllConfigs(ctx)
    91  	utils.SetNodeConfig(ctx, &cfg.Node)
    92  
    93  	password := getPassPhrase("Your new validator key is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(ctx))
    94  
    95  	privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), rand.Reader)
    96  	if err != nil {
    97  		utils.Fatalf("Failed to create account: %v", err)
    98  	}
    99  	privateKey := crypto.FromECDSA(privateKeyECDSA)
   100  	publicKey := validatorpk.PubKey{
   101  		Raw:  crypto.FromECDSAPub(&privateKeyECDSA.PublicKey),
   102  		Type: validatorpk.Types.Secp256k1,
   103  	}
   104  
   105  	valKeystore := valkeystore.NewDefaultFileRawKeystore(path.Join(getValKeystoreDir(cfg.Node), "validator"))
   106  	err = valKeystore.Add(publicKey, privateKey, password)
   107  	if err != nil {
   108  		utils.Fatalf("Failed to create account: %v", err)
   109  	}
   110  
   111  	// Sanity check
   112  	_, err = valKeystore.Get(publicKey, password)
   113  	if err != nil {
   114  		utils.Fatalf("Failed to decrypt the account: %v", err)
   115  	}
   116  
   117  	fmt.Printf("\nYour new key was generated\n\n")
   118  	fmt.Printf("Public key:                  %s\n", publicKey.String())
   119  	fmt.Printf("Path of the secret key file: %s\n\n", valKeystore.PathOf(publicKey))
   120  	fmt.Printf("- You can share your public key with anyone. Others need it to validate messages from you.\n")
   121  	fmt.Printf("- You must NEVER share the secret key with anyone! The key controls access to your validator!\n")
   122  	fmt.Printf("- You must BACKUP your key file! Without the key, it's impossible to operate the validator!\n")
   123  	fmt.Printf("- You must REMEMBER your password! Without the password, it's impossible to decrypt the key!\n\n")
   124  	return nil
   125  }
   126  
   127  // validatorKeyConvert converts account key to validator key.
   128  func validatorKeyConvert(ctx *cli.Context) error {
   129  	if len(ctx.Args()) < 2 {
   130  		utils.Fatalf("This command requires 2 arguments.")
   131  	}
   132  	cfg := makeAllConfigs(ctx)
   133  	utils.SetNodeConfig(ctx, &cfg.Node)
   134  
   135  	_, _, keydir, _ := cfg.Node.AccountConfig()
   136  
   137  	pubkeyStr := ctx.Args().Get(1)
   138  	pubkey, err := validatorpk.FromString(pubkeyStr)
   139  	if err != nil {
   140  		utils.Fatalf("Failed to decode the validator pubkey: %v", err)
   141  	}
   142  
   143  	var acckeypath string
   144  	if strings.HasPrefix(ctx.Args().First(), "0x") {
   145  		acckeypath, err = FindAccountKeypath(common.HexToAddress(ctx.Args().First()), keydir)
   146  		if err != nil {
   147  			utils.Fatalf("Failed to find the account: %v", err)
   148  		}
   149  	} else {
   150  		acckeypath = ctx.Args().First()
   151  	}
   152  
   153  	valkeypath := path.Join(keydir, "validator", common.Bytes2Hex(pubkey.Bytes()))
   154  	err = encryption.MigrateAccountToValidatorKey(acckeypath, valkeypath, pubkey)
   155  	if err != nil {
   156  		utils.Fatalf("Failed to migrate the account key: %v", err)
   157  	}
   158  	fmt.Println("\nYour key was converted and saved to " + valkeypath)
   159  	return nil
   160  }