262 lines
7.0 KiB
Go
262 lines
7.0 KiB
Go
package debug
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/cosmos/cosmos-sdk/client"
|
|
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
|
|
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
|
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
"github.com/cosmos/cosmos-sdk/types/errors"
|
|
"github.com/cosmos/cosmos-sdk/version"
|
|
|
|
legacybech32 "github.com/cosmos/cosmos-sdk/types/bech32/legacybech32"
|
|
)
|
|
|
|
var (
|
|
flagPubkeyType = "type"
|
|
)
|
|
|
|
// Cmd creates a main CLI command
|
|
func Cmd() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "debug",
|
|
Short: "Tool for helping with debugging your application",
|
|
RunE: client.ValidateCmd,
|
|
}
|
|
|
|
cmd.AddCommand(PubkeyCmd())
|
|
cmd.AddCommand(PubkeyRawCmd())
|
|
cmd.AddCommand(AddrCmd())
|
|
cmd.AddCommand(RawBytesCmd())
|
|
|
|
return cmd
|
|
}
|
|
|
|
// getPubKeyFromString decodes SDK PubKey using JSON marshaler.
|
|
func getPubKeyFromString(ctx client.Context, pkstr string) (cryptotypes.PubKey, error) {
|
|
var pk cryptotypes.PubKey
|
|
err := ctx.Codec.UnmarshalInterfaceJSON([]byte(pkstr), &pk)
|
|
return pk, err
|
|
}
|
|
|
|
func PubkeyCmd() *cobra.Command {
|
|
return &cobra.Command{
|
|
Use: "pubkey [pubkey]",
|
|
Short: "Decode a pubkey from proto JSON",
|
|
Long: fmt.Sprintf(`Decode a pubkey from proto JSON and display it's address.
|
|
|
|
Example:
|
|
$ %s debug pubkey '{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AurroA7jvfPd1AadmmOvWM2rJSwipXfRf8yD6pLbA2DJ"}'
|
|
`, version.AppName),
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
clientCtx := client.GetClientContextFromCmd(cmd)
|
|
pk, err := getPubKeyFromString(clientCtx, args[0])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
cmd.Println("Address:", pk.Address())
|
|
cmd.Println("PubKey Hex:", hex.EncodeToString(pk.Bytes()))
|
|
return nil
|
|
},
|
|
}
|
|
}
|
|
|
|
func bytesToPubkey(bz []byte, keytype string) (cryptotypes.PubKey, bool) {
|
|
if keytype == "ed25519" {
|
|
if len(bz) == ed25519.PubKeySize {
|
|
return &ed25519.PubKey{Key: bz}, true
|
|
}
|
|
}
|
|
|
|
if len(bz) == secp256k1.PubKeySize {
|
|
return &secp256k1.PubKey{Key: bz}, true
|
|
}
|
|
return nil, false
|
|
}
|
|
|
|
// getPubKeyFromRawString returns a PubKey (PubKeyEd25519 or PubKeySecp256k1) by attempting
|
|
// to decode the pubkey string from hex, base64, and finally bech32. If all
|
|
// encodings fail, an error is returned.
|
|
func getPubKeyFromRawString(pkstr string, keytype string) (cryptotypes.PubKey, error) {
|
|
// Try hex decoding
|
|
bz, err := hex.DecodeString(pkstr)
|
|
if err == nil {
|
|
pk, ok := bytesToPubkey(bz, keytype)
|
|
if ok {
|
|
return pk, nil
|
|
}
|
|
}
|
|
|
|
bz, err = base64.StdEncoding.DecodeString(pkstr)
|
|
if err == nil {
|
|
pk, ok := bytesToPubkey(bz, keytype)
|
|
if ok {
|
|
return pk, nil
|
|
}
|
|
}
|
|
|
|
pk, err := legacybech32.UnmarshalPubKey(legacybech32.AccPK, pkstr)
|
|
if err == nil {
|
|
return pk, nil
|
|
}
|
|
|
|
pk, err = legacybech32.UnmarshalPubKey(legacybech32.ValPK, pkstr)
|
|
if err == nil {
|
|
return pk, nil
|
|
}
|
|
|
|
pk, err = legacybech32.UnmarshalPubKey(legacybech32.ConsPK, pkstr)
|
|
if err == nil {
|
|
return pk, nil
|
|
}
|
|
|
|
return nil, fmt.Errorf("pubkey '%s' invalid; expected hex, base64, or bech32 of correct size", pkstr)
|
|
}
|
|
|
|
func PubkeyRawCmd() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "pubkey-raw [pubkey] -t [{ed25519, secp256k1}]",
|
|
Short: "Decode a ED25519 or secp256k1 pubkey from hex, base64, or bech32",
|
|
Long: fmt.Sprintf(`Decode a pubkey from hex, base64, or bech32.
|
|
Example:
|
|
$ %s debug pubkey-raw TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz
|
|
$ %s debug pubkey-raw cosmos1e0jnq2sun3dzjh8p2xq95kk0expwmd7shwjpfg
|
|
`, version.AppName, version.AppName),
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
clientCtx := client.GetClientContextFromCmd(cmd)
|
|
|
|
pubkeyType, err := cmd.Flags().GetString(flagPubkeyType)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
pubkeyType = strings.ToLower(pubkeyType)
|
|
if pubkeyType != "secp256k1" && pubkeyType != "ed25519" {
|
|
return errors.Wrapf(errors.ErrInvalidType, "invalid pubkey type, expected oneof ed25519 or secp256k1")
|
|
}
|
|
|
|
pk, err := getPubKeyFromRawString(args[0], pubkeyType)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var consensusPub string
|
|
edPK, ok := pk.(*ed25519.PubKey)
|
|
if ok && pubkeyType == "ed25519" {
|
|
consensusPub, err = legacybech32.MarshalPubKey(legacybech32.ConsPK, edPK)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cmd.Printf("Hex: %X\n", edPK.Key)
|
|
}
|
|
cmd.Println("Parsed key as", pk.Type())
|
|
|
|
pubKeyJSONBytes, err := clientCtx.LegacyAmino.MarshalJSON(pk)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
accPub, err := legacybech32.MarshalPubKey(legacybech32.AccPK, pk)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
valPub, err := legacybech32.MarshalPubKey(legacybech32.ValPK, pk)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
cmd.Println("Address:", pk.Address())
|
|
cmd.Println("JSON (base64):", string(pubKeyJSONBytes))
|
|
cmd.Println("Bech32 Acc:", accPub)
|
|
cmd.Println("Bech32 Validator Operator:", valPub)
|
|
if pubkeyType == "ed25519" {
|
|
|
|
cmd.Println("Bech32 Validator Consensus:", consensusPub)
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|
|
cmd.Flags().StringP(flagPubkeyType, "t", "ed25519", "Pubkey type to decode (oneof secp256k1, ed25519)")
|
|
return cmd
|
|
}
|
|
|
|
func AddrCmd() *cobra.Command {
|
|
return &cobra.Command{
|
|
Use: "addr [address]",
|
|
Short: "Convert an address between hex and bech32",
|
|
Long: fmt.Sprintf(`Convert an address between hex encoding and bech32.
|
|
|
|
Example:
|
|
$ %s debug addr cosmos1e0jnq2sun3dzjh8p2xq95kk0expwmd7shwjpfg
|
|
`, version.AppName),
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
|
|
addrString := args[0]
|
|
var addr []byte
|
|
|
|
// try hex, then bech32
|
|
var err error
|
|
addr, err = hex.DecodeString(addrString)
|
|
if err != nil {
|
|
var err2 error
|
|
addr, err2 = sdk.AccAddressFromBech32(addrString)
|
|
if err2 != nil {
|
|
var err3 error
|
|
addr, err3 = sdk.ValAddressFromBech32(addrString)
|
|
|
|
if err3 != nil {
|
|
return fmt.Errorf("expected hex or bech32. Got errors: hex: %v, bech32 acc: %v, bech32 val: %v", err, err2, err3)
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
cmd.Println("Address:", addr)
|
|
cmd.Printf("Address (hex): %X\n", addr)
|
|
cmd.Printf("Bech32 Acc: %s\n", sdk.AccAddress(addr))
|
|
cmd.Printf("Bech32 Val: %s\n", sdk.ValAddress(addr))
|
|
return nil
|
|
},
|
|
}
|
|
}
|
|
|
|
func RawBytesCmd() *cobra.Command {
|
|
return &cobra.Command{
|
|
Use: "raw-bytes [raw-bytes]",
|
|
Short: "Convert raw bytes output (eg. [10 21 13 255]) to hex",
|
|
Long: fmt.Sprintf(`Convert raw-bytes to hex.
|
|
|
|
Example:
|
|
$ %s debug raw-bytes [72 101 108 108 111 44 32 112 108 97 121 103 114 111 117 110 100]
|
|
`, version.AppName),
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(_ *cobra.Command, args []string) error {
|
|
stringBytes := args[0]
|
|
stringBytes = strings.Trim(stringBytes, "[")
|
|
stringBytes = strings.Trim(stringBytes, "]")
|
|
spl := strings.Split(stringBytes, " ")
|
|
|
|
byteArray := []byte{}
|
|
for _, s := range spl {
|
|
b, err := strconv.ParseInt(s, 10, 8)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
byteArray = append(byteArray, byte(b))
|
|
}
|
|
fmt.Printf("%X\n", byteArray)
|
|
return nil
|
|
},
|
|
}
|
|
}
|