code.vegaprotocol.io/vega@v0.79.0/cmd/vegawallet/commands/key_generate.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package cmd
    17  
    18  import (
    19  	"context"
    20  	"errors"
    21  	"fmt"
    22  	"io"
    23  	"os"
    24  
    25  	"code.vegaprotocol.io/vega/cmd/vegawallet/commands/cli"
    26  	"code.vegaprotocol.io/vega/cmd/vegawallet/commands/flags"
    27  	"code.vegaprotocol.io/vega/cmd/vegawallet/commands/printer"
    28  	"code.vegaprotocol.io/vega/wallet/api"
    29  	"code.vegaprotocol.io/vega/wallet/wallets"
    30  
    31  	"github.com/spf13/cobra"
    32  )
    33  
    34  var (
    35  	generateKeyLong = cli.LongDesc(`
    36  		Generate a new Ed25519 key pair in the specified wallet.
    37  	`)
    38  
    39  	generateKeyExample = cli.Examples(`
    40  		# Generate a key pair
    41  		{{.Software}} key generate --wallet WALLET
    42  
    43  		# Generate a key pair with additional metadata (name = my-wallet and type = validation)
    44  		{{.Software}} key generate --wallet WALLET --meta "name:my-wallet,type:validation"
    45  
    46  		# Generate a key pair with custom name
    47  		{{.Software}} key generate --wallet WALLET --meta "name:my-wallet"
    48  	`)
    49  )
    50  
    51  type GenerateKeyHandler func(api.AdminGenerateKeyParams, string) (api.AdminGenerateKeyResult, error)
    52  
    53  func NewCmdGenerateKey(w io.Writer, rf *RootFlags) *cobra.Command {
    54  	h := func(params api.AdminGenerateKeyParams, passphrase string) (api.AdminGenerateKeyResult, error) {
    55  		ctx := context.Background()
    56  
    57  		walletStore, err := wallets.InitialiseStore(rf.Home, false)
    58  		if err != nil {
    59  			return api.AdminGenerateKeyResult{}, fmt.Errorf("couldn't initialise wallets store: %w", err)
    60  		}
    61  		defer walletStore.Close()
    62  
    63  		if _, errDetails := api.NewAdminUnlockWallet(walletStore).Handle(ctx, api.AdminUnlockWalletParams{
    64  			Wallet:     params.Wallet,
    65  			Passphrase: passphrase,
    66  		}); errDetails != nil {
    67  			return api.AdminGenerateKeyResult{}, errors.New(errDetails.Data)
    68  		}
    69  
    70  		rawResult, errDetails := api.NewAdminGenerateKey(walletStore).Handle(ctx, params)
    71  		if errDetails != nil {
    72  			return api.AdminGenerateKeyResult{}, errors.New(errDetails.Data)
    73  		}
    74  		return rawResult.(api.AdminGenerateKeyResult), nil
    75  	}
    76  
    77  	return BuildCmdGenerateKey(w, h, rf)
    78  }
    79  
    80  func BuildCmdGenerateKey(w io.Writer, handler GenerateKeyHandler, rf *RootFlags) *cobra.Command {
    81  	f := &GenerateKeyFlags{}
    82  
    83  	cmd := &cobra.Command{
    84  		Use:     "generate",
    85  		Short:   "Generate a new key pair in a given wallet",
    86  		Long:    generateKeyLong,
    87  		Example: generateKeyExample,
    88  		RunE: func(_ *cobra.Command, _ []string) error {
    89  			req, pass, err := f.Validate()
    90  			if err != nil {
    91  				return err
    92  			}
    93  
    94  			resp, err := handler(req, pass)
    95  			if err != nil {
    96  				return err
    97  			}
    98  
    99  			switch rf.Output {
   100  			case flags.InteractiveOutput:
   101  				PrintGenerateKeyResponse(w, req, resp)
   102  			case flags.JSONOutput:
   103  				return printer.FprintJSON(w, resp)
   104  			}
   105  
   106  			return nil
   107  		},
   108  	}
   109  
   110  	cmd.Flags().StringVarP(&f.Wallet,
   111  		"wallet", "w",
   112  		"",
   113  		"The wallet where the key is generated in",
   114  	)
   115  	cmd.Flags().StringVarP(&f.PassphraseFile,
   116  		"passphrase-file", "p",
   117  		"",
   118  		"Path to the file containing the wallet's passphrase",
   119  	)
   120  	cmd.Flags().StringSliceVarP(&f.RawMetadata,
   121  		"meta", "m",
   122  		[]string{},
   123  		`Metadata to add to the generated key-pair: "my-key1:my-value1,my-key2:my-value2"`,
   124  	)
   125  
   126  	autoCompleteWallet(cmd, rf.Home, "wallet")
   127  
   128  	return cmd
   129  }
   130  
   131  type GenerateKeyFlags struct {
   132  	Wallet         string
   133  	PassphraseFile string
   134  	RawMetadata    []string
   135  }
   136  
   137  func (f *GenerateKeyFlags) Validate() (api.AdminGenerateKeyParams, string, error) {
   138  	req := api.AdminGenerateKeyParams{}
   139  
   140  	if len(f.Wallet) == 0 {
   141  		return api.AdminGenerateKeyParams{}, "", flags.MustBeSpecifiedError("wallet")
   142  	}
   143  	req.Wallet = f.Wallet
   144  
   145  	metadata, err := cli.ParseMetadata(f.RawMetadata)
   146  	if err != nil {
   147  		return api.AdminGenerateKeyParams{}, "", err
   148  	}
   149  	req.Metadata = metadata
   150  
   151  	passphrase, err := flags.GetPassphrase(f.PassphraseFile)
   152  	if err != nil {
   153  		return api.AdminGenerateKeyParams{}, "", err
   154  	}
   155  
   156  	return req, passphrase, nil
   157  }
   158  
   159  func PrintGenerateKeyResponse(w io.Writer, req api.AdminGenerateKeyParams, resp api.AdminGenerateKeyResult) {
   160  	p := printer.NewInteractivePrinter(w)
   161  
   162  	str := p.String()
   163  	defer p.Print(str)
   164  
   165  	str.CheckMark().Text("Key pair has been generated in wallet ").Bold(req.Wallet).NextLine()
   166  	str.CheckMark().SuccessText("Generating a key pair succeeded").NextSection()
   167  	str.Text("Public key:").NextLine()
   168  	str.WarningText(resp.PublicKey).NextLine()
   169  	str.Text("Metadata:").NextLine()
   170  	printMeta(str, resp.Metadata)
   171  	str.NextSection()
   172  	str.BlueArrow().InfoText("Run the service").NextLine()
   173  	str.Text("Now, you can run the service. See the following command:").NextSection()
   174  	str.Code(fmt.Sprintf("%s service run --help", os.Args[0])).NextLine()
   175  }