Skip to content

Commit

Permalink
feat: add base64 Pubkeys from cli (#17639)
Browse files Browse the repository at this point in the history
Co-authored-by: Aleksandr Bezobchuk <[email protected]>
  • Loading branch information
JulianToledano and alexanderbez authored Sep 7, 2023
1 parent 33eead4 commit 933d042
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Features

* (client/keys) [#17639](https://github.com/cosmos/cosmos-sdk/pull/17639) Allows using and saving public keys encoded as base64
* (client) [#17513](https://github.com/cosmos/cosmos-sdk/pull/17513) Allow overwritting `client.toml`. Use `client.CreateClientConfig` in place of `client.ReadFromClientConfig` and provide a custom template and a custom config.
* (x/bank) [#14224](https://github.com/cosmos/cosmos-sdk/pull/14224) Allow injection of restrictions on transfers using `AppendSendRestriction` or `PrependSendRestriction`.
* (genutil) [#17571](https://github.com/cosmos/cosmos-sdk/pull/17571) Allow creation of `AppGenesis` without a file lookup.
Expand Down
58 changes: 49 additions & 9 deletions client/keys/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keys
import (
"bufio"
"bytes"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
Expand All @@ -15,6 +16,7 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/input"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
Expand All @@ -23,15 +25,16 @@ import (
)

const (
flagInteractive = "interactive"
flagRecover = "recover"
flagNoBackup = "no-backup"
flagCoinType = "coin-type"
flagAccount = "account"
flagIndex = "index"
flagMultisig = "multisig"
flagNoSort = "nosort"
flagHDPath = "hd-path"
flagInteractive = "interactive"
flagRecover = "recover"
flagNoBackup = "no-backup"
flagCoinType = "coin-type"
flagAccount = "account"
flagIndex = "index"
flagMultisig = "multisig"
flagNoSort = "nosort"
flagHDPath = "hd-path"
flagPubKeyBase64 = "pubkey-base64"

// DefaultKeyPass contains the default key password for genesis transactions
DefaultKeyPass = "12345678"
Expand Down Expand Up @@ -69,6 +72,7 @@ Example:
f.Int(flagMultiSigThreshold, 1, "K out of N required signatures. For use in conjunction with --multisig")
f.Bool(flagNoSort, false, "Keys passed to --multisig are taken in the order they're supplied")
f.String(FlagPublicKey, "", "Parse a public key in JSON format and saves key info to <name> file.")
f.String(flagPubKeyBase64, "", "Parse a public key in base64 format and saves key info.")
f.BoolP(flagInteractive, "i", false, "Interactively prompt user for BIP39 passphrase and mnemonic")
f.Bool(flags.FlagUseLedger, false, "Store a local reference to a private key on a Ledger device")
f.Bool(flagRecover, false, "Provide seed phrase to recover existing key instead of creating")
Expand Down Expand Up @@ -189,6 +193,10 @@ func runAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
}

pubKey, _ := cmd.Flags().GetString(FlagPublicKey)
pubKeyBase64, _ := cmd.Flags().GetString(flagPubKeyBase64)
if pubKey != "" && pubKeyBase64 != "" {
return fmt.Errorf(`flags %s and %s cannot be used simultaneously`, FlagPublicKey, flagPubKeyBase64)
}
if pubKey != "" {
var pk cryptotypes.PubKey
if err = ctx.Codec.UnmarshalInterfaceJSON([]byte(pubKey), &pk); err != nil {
Expand All @@ -202,6 +210,38 @@ func runAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf

return printCreate(ctx, cmd, k, false, "", outputFormat)
}
if pubKeyBase64 != "" {
b64, err := base64.StdEncoding.DecodeString(pubKeyBase64)
if err != nil {
return err
}

var pk cryptotypes.PubKey
// create an empty pubkey in order to get the algo TypeUrl.
tempAny, err := codectypes.NewAnyWithValue(algo.Generate()([]byte{}).PubKey())
if err != nil {
return err
}

jsonPub, err := json.Marshal(struct {
Type string `json:"@type,omitempty"`
Key string `json:"key,omitempty"`
}{tempAny.TypeUrl, string(b64)})
if err != nil {
return fmt.Errorf("failed to JSON marshal typeURL and base64 key: %w", err)
}

if err = ctx.Codec.UnmarshalInterfaceJSON(jsonPub, &pk); err != nil {
return err
}

k, err := kb.SaveOfflineKey(name, pk)
if err != nil {
return fmt.Errorf("failed to save offline key: %w", err)
}

return printCreate(ctx, cmd, k, false, "", outputFormat)
}

coinType, _ := cmd.Flags().GetUint32(flagCoinType)
account, _ := cmd.Flags().GetUint32(flagAccount)
Expand Down
19 changes: 19 additions & 0 deletions client/keys/add_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ func Test_runAddCmdBasic(t *testing.T) {
func Test_runAddCmdDryRun(t *testing.T) {
pubkey1 := `{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AtObiFVE4s+9+RX5SP8TN9r2mxpoaT4eGj9CJfK7VRzN"}`
pubkey2 := `{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A/se1vkqgdQ7VJQCM4mxN+L+ciGhnnJ4XYsQCRBMrdRi"}`
b64Pubkey := "QWhnOHhpdXBJcGZ2UlR2ak5la1ExclROUThTOW96YjdHK2RYQmFLVjl4aUo="
cdc := moduletestutil.MakeTestEncodingConfig().Codec

testData := []struct {
Expand Down Expand Up @@ -189,6 +190,24 @@ func Test_runAddCmdDryRun(t *testing.T) {
},
added: false,
},
{
name: "base64 pubkey account is added",
args: []string{
"testkey",
fmt.Sprintf("--%s=%s", flags.FlagDryRun, "false"),
fmt.Sprintf("--%s=%s", flagPubKeyBase64, b64Pubkey),
},
added: true,
},
{
name: "base64 pubkey account is not added with dry run",
args: []string{
"testkey",
fmt.Sprintf("--%s=%s", flags.FlagDryRun, "true"),
fmt.Sprintf("--%s=%s", flagPubKeyBase64, b64Pubkey),
},
added: false,
},
}
for _, tt := range testData {
tt := tt
Expand Down

0 comments on commit 933d042

Please sign in to comment.