github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/client/keys/show.go (about) 1 package keys 2 3 import ( 4 "errors" 5 "fmt" 6 7 "github.com/spf13/cobra" 8 "github.com/spf13/viper" 9 10 tmcrypto "github.com/fibonacci-chain/fbc/libs/tendermint/crypto" 11 "github.com/fibonacci-chain/fbc/libs/tendermint/crypto/multisig" 12 "github.com/fibonacci-chain/fbc/libs/tendermint/libs/cli" 13 14 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/flags" 15 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/crypto" 16 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/crypto/keys" 17 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 18 ) 19 20 const ( 21 // FlagAddress is the flag for the user's address on the command line. 22 FlagAddress = "address" 23 // FlagPublicKey represents the user's public key on the command line. 24 FlagPublicKey = "pubkey" 25 // FlagBechPrefix defines a desired Bech32 prefix encoding for a key. 26 FlagBechPrefix = "bech" 27 // FlagDevice indicates that the information should be shown in the device 28 FlagDevice = "device" 29 30 flagMultiSigThreshold = "multisig-threshold" 31 32 defaultMultiSigKeyName = "multi" 33 ) 34 35 // ShowKeysCmd shows key information for a given key name. 36 func ShowKeysCmd() *cobra.Command { 37 cmd := &cobra.Command{ 38 Use: "show [name [name...]]", 39 Short: "Show key info for the given name", 40 Long: `Return public details of a single local key. If multiple names are 41 provided, then an ephemeral multisig key will be created under the name "multi" 42 consisting of all the keys provided by name and multisig threshold.`, 43 Args: cobra.MinimumNArgs(1), 44 RunE: runShowCmd, 45 } 46 47 cmd.Flags().String(FlagBechPrefix, sdk.PrefixAccount, "The Bech32 prefix encoding for a key (acc|val|cons)") 48 cmd.Flags().BoolP(FlagAddress, "a", false, "Output the address only (overrides --output)") 49 cmd.Flags().BoolP(FlagPublicKey, "p", false, "Output the public key only (overrides --output)") 50 cmd.Flags().BoolP(FlagDevice, "d", false, "Output the address in a ledger device") 51 cmd.Flags().Uint(flagMultiSigThreshold, 1, "K out of N required signatures") 52 cmd.Flags().Bool(flags.FlagIndentResponse, false, "Add indent to JSON response") 53 54 return cmd 55 } 56 57 func runShowCmd(cmd *cobra.Command, args []string) (err error) { 58 var info keys.Info 59 60 kb, err := keys.NewKeyring(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), cmd.InOrStdin()) 61 if err != nil { 62 return err 63 } 64 if len(args) == 1 { 65 info, err = kb.Get(args[0]) 66 if err != nil { 67 return err 68 } 69 } else { 70 pks := make([]tmcrypto.PubKey, len(args)) 71 for i, keyName := range args { 72 info, err := kb.Get(keyName) 73 if err != nil { 74 return err 75 } 76 77 pks[i] = info.GetPubKey() 78 } 79 80 multisigThreshold := viper.GetInt(flagMultiSigThreshold) 81 err = validateMultisigThreshold(multisigThreshold, len(args)) 82 if err != nil { 83 return err 84 } 85 86 multikey := multisig.NewPubKeyMultisigThreshold(multisigThreshold, pks) 87 info = keys.NewMultiInfo(defaultMultiSigKeyName, multikey) 88 } 89 90 isShowAddr := viper.GetBool(FlagAddress) 91 isShowPubKey := viper.GetBool(FlagPublicKey) 92 isShowDevice := viper.GetBool(FlagDevice) 93 94 isOutputSet := false 95 tmp := cmd.Flag(cli.OutputFlag) 96 if tmp != nil { 97 isOutputSet = tmp.Changed 98 } 99 100 if isShowAddr && isShowPubKey { 101 return errors.New("cannot use both --address and --pubkey at once") 102 } 103 104 if isOutputSet && (isShowAddr || isShowPubKey) { 105 return errors.New("cannot use --output with --address or --pubkey") 106 } 107 108 bechKeyOut, err := getBechKeyOut(viper.GetString(FlagBechPrefix)) 109 if err != nil { 110 return err 111 } 112 113 switch { 114 case isShowAddr: 115 printKeyAddress(info, bechKeyOut) 116 case isShowPubKey: 117 printPubKey(info, bechKeyOut) 118 default: 119 printKeyInfo(info, bechKeyOut) 120 } 121 122 if isShowDevice { 123 if isShowPubKey { 124 return fmt.Errorf("the device flag (-d) can only be used for addresses not pubkeys") 125 } 126 if viper.GetString(FlagBechPrefix) != "acc" { 127 return fmt.Errorf("the device flag (-d) can only be used for accounts") 128 } 129 // Override and show in the device 130 if info.GetType() != keys.TypeLedger { 131 return fmt.Errorf("the device flag (-d) can only be used for accounts stored in devices") 132 } 133 134 hdpath, err := info.GetPath() 135 if err != nil { 136 return nil 137 } 138 139 return crypto.LedgerShowAddress(*hdpath, info.GetPubKey()) 140 } 141 142 return nil 143 } 144 145 func validateMultisigThreshold(k, nKeys int) error { 146 if k <= 0 { 147 return fmt.Errorf("threshold must be a positive integer") 148 } 149 if nKeys < k { 150 return fmt.Errorf( 151 "threshold k of n multisignature: %d < %d", nKeys, k) 152 } 153 return nil 154 } 155 156 func getBechKeyOut(bechPrefix string) (bechKeyOutFn, error) { 157 switch bechPrefix { 158 case sdk.PrefixAccount: 159 return keys.Bech32KeyOutput, nil 160 case sdk.PrefixValidator: 161 return keys.Bech32ValKeyOutput, nil 162 case sdk.PrefixConsensus: 163 return keys.Bech32ConsKeyOutput, nil 164 } 165 166 return nil, fmt.Errorf("invalid Bech32 prefix encoding provided: %s", bechPrefix) 167 }