refactor!: Keyring migration (#9695)

<!--
The default pull request template is for types feat, fix, or refactor.
For other templates, add one of the following parameters to the url:
- template=docs.md
- template=other.md
-->

## Description

The draft PR #9222 
Closes: #7108

<!-- Add a description of the changes that this PR introduces and the files that
are the most critical to review. -->

- implement proto definition for `Record` 
- rename `Info.go` to `legacyInfo.go` within `keyring` package
- implement CLI `migrate` command that migrates all keys from  legacyInfo to proto according to @robert-zaremba migration [algorithm](https://github.com/cosmos/cosmos-sdk/pull/9222/#discussion_r624683839)
- remove legacy keybase entirely.
- add `Migrate` and `MigrateAll` functions  in `keyring.go` for single key and all keys migration
- add tests
- fix tests

---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] added `!` to the type prefix if API or client breaking change
- [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [ ] provided a link to the relevant issue or specification
- [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [x] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [ ] added a changelog entry to `CHANGELOG.md`
- [ ] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [ ] updated the relevant documentation or specification
- [x] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed 
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
This commit is contained in:
Andrei Ivasko 2021-09-20 15:02:15 +03:00 committed by GitHub
parent a0ecfe54ea
commit 6cbbd6da75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
80 changed files with 4118 additions and 1320 deletions

View File

@ -48,6 +48,23 @@ Ref: https://keepachangelog.com/en/1.0.0/
### API Breaking Changes
* [\#9695](https://github.com/cosmos/cosmos-sdk/pull/9695) Migrate keys from `Info` -> `Record`
* Add new `codec.Codec` argument in:
* `keyring.NewInMemory`
* `keyring.New`
* Rename:
* `SavePubKey` to `SaveOfflineKey`.
* `NewMultiInfo`, `NewLedgerInfo` to `NewLegacyMultiInfo`, `newLegacyLedgerInfo` respectively. Move them into `legacy_info.go`.
* `NewOfflineInfo` to `newLegacyOfflineInfo` and move it to `migration_test.go`.
* Return:
*`keyring.Record, error` in `SaveOfflineKey`, `SaveLedgerKey`, `SaveMultiSig`, `Key` and `KeyByAddress`.
*`keyring.Record` instead of `Info` in `NewMnemonic` and `List`.
* Remove `algo` argument from :
* `SaveOfflineKey`
* Take `keyring.Record` instead of `Info` as first argument in:
* `MkConsKeyOutput`
* `MkValKeyOutput`
* `MkAccKeyOutput`
* [\#10077](https://github.com/cosmos/cosmos-sdk/pull/10077) Remove telemetry on `GasKV` and `CacheKV` store Get/Set operations, significantly improving their performance.
* [\#10022](https://github.com/cosmos/cosmos-sdk/pull/10022) `AuthKeeper` interface in `x/auth` now includes a function `HasAccount`.
* [\#9759](https://github.com/cosmos/cosmos-sdk/pull/9759) `NewAccountKeeeper` in `x/auth` now takes an additional `bech32Prefix` argument that represents `sdk.Bech32MainPrefix`.
@ -83,6 +100,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### CLI Breaking Changes
* [\#9695](https://github.com/cosmos/cosmos-sdk/pull/9695) `<app> keys migrate` CLI command now takes no arguments
* [\#9246](https://github.com/cosmos/cosmos-sdk/pull/9246) Removed the CLI flag `--setup-config-only` from the `testnet` command and added the subcommand `init-files`.
### Improvements

View File

@ -323,27 +323,32 @@ func GetFromFields(kr keyring.Keyring, from string, genOnly bool) (sdk.AccAddres
return nil, "", 0, nil
}
var info keyring.Info
var k *keyring.Record
if addr, err := sdk.AccAddressFromBech32(from); err == nil {
info, err = kr.KeyByAddress(addr)
k, err = kr.KeyByAddress(addr)
if err != nil {
return nil, "", 0, err
}
} else {
info, err = kr.Key(from)
k, err = kr.Key(from)
if err != nil {
return nil, "", 0, err
}
}
return info.GetAddress(), info.GetName(), info.GetType(), nil
addr, err := k.GetAddress()
if err != nil {
return nil, "", 0, err
}
return addr, k.Name, k.GetType(), nil
}
// NewKeyringFromBackend gets a Keyring object from a backend
func NewKeyringFromBackend(ctx Context, backend string) (keyring.Keyring, error) {
if ctx.GenerateOnly || ctx.Simulate {
return keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, ctx.KeyringDir, ctx.Input, ctx.KeyringOptions...)
backend = keyring.BackendMemory
}
return keyring.New(sdk.KeyringServiceName(), backend, ctx.KeyringDir, ctx.Input, ctx.KeyringOptions...)
return keyring.New(sdk.KeyringServiceName(), backend, ctx.KeyringDir, ctx.Input, ctx.Codec, ctx.KeyringOptions...)
}

View File

@ -7,7 +7,7 @@ import (
"fmt"
"sort"
bip39 "github.com/cosmos/go-bip39"
"github.com/cosmos/go-bip39"
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client"
@ -119,7 +119,7 @@ func runAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
if dryRun, _ := cmd.Flags().GetBool(flags.FlagDryRun); dryRun {
// use in memory keybase
kb = keyring.NewInMemory()
kb = keyring.NewInMemory(ctx.Codec)
} else {
_, err = kb.Key(name)
if err == nil {
@ -153,7 +153,11 @@ func runAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
return err
}
pks[i] = k.GetPubKey()
key, err := k.GetPubKey()
if err != nil {
return err
}
pks[i] = key
}
if noSort, _ := cmd.Flags().GetBool(flagNoSort); !noSort {
@ -163,29 +167,28 @@ func runAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
}
pk := multisig.NewLegacyAminoPubKey(multisigThreshold, pks)
info, err := kb.SaveMultisig(name, pk)
k, err := kb.SaveMultisig(name, pk)
if err != nil {
return err
}
return printCreate(cmd, info, false, "", outputFormat)
return printCreate(cmd, k, false, "", outputFormat)
}
}
pubKey, _ := cmd.Flags().GetString(FlagPublicKey)
if pubKey != "" {
var pk cryptotypes.PubKey
err = ctx.Codec.UnmarshalInterfaceJSON([]byte(pubKey), &pk)
if err = ctx.Codec.UnmarshalInterfaceJSON([]byte(pubKey), &pk); err != nil {
return err
}
k, err := kb.SaveOfflineKey(name, pk)
if err != nil {
return err
}
info, err := kb.SavePubKey(name, pk, algo.Name())
if err != nil {
return err
}
return printCreate(cmd, info, false, "", outputFormat)
return printCreate(cmd, k, false, "", outputFormat)
}
coinType, _ := cmd.Flags().GetUint32(flagCoinType)
@ -203,13 +206,12 @@ func runAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
// If we're using ledger, only thing we need is the path and the bech32 prefix.
if useLedger {
bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix()
info, err := kb.SaveLedgerKey(name, algo, bech32PrefixAccAddr, coinType, account, index)
k, err := kb.SaveLedgerKey(name, hd.Secp256k1, bech32PrefixAccAddr, coinType, account, index)
if err != nil {
return err
}
return printCreate(cmd, info, false, "", outputFormat)
return printCreate(cmd, k, false, "", outputFormat)
}
// Get bip39 mnemonic
@ -271,7 +273,7 @@ func runAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
}
}
info, err := kb.NewAccount(name, mnemonic, bip39Passphrase, hdPath, algo)
k, err := kb.NewAccount(name, mnemonic, bip39Passphrase, hdPath, algo)
if err != nil {
return err
}
@ -283,14 +285,14 @@ func runAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *buf
mnemonic = ""
}
return printCreate(cmd, info, showMnemonic, mnemonic, outputFormat)
return printCreate(cmd, k, showMnemonic, mnemonic, outputFormat)
}
func printCreate(cmd *cobra.Command, info keyring.Info, showMnemonic bool, mnemonic string, outputFormat string) error {
func printCreate(cmd *cobra.Command, k *keyring.Record, showMnemonic bool, mnemonic, outputFormat string) error {
switch outputFormat {
case OutputFormatText:
cmd.PrintErrln()
printKeyInfo(cmd.OutOrStdout(), info, keyring.MkAccKeyOutput, outputFormat)
printKeyringRecord(cmd.OutOrStdout(), k, keyring.MkAccKeyOutput, outputFormat)
// print mnemonic unless requested not to.
if showMnemonic {
@ -300,7 +302,7 @@ func printCreate(cmd *cobra.Command, info keyring.Info, showMnemonic bool, mnemo
fmt.Fprintln(cmd.ErrOrStderr(), mnemonic)
}
case OutputFormatJSON:
out, err := keyring.MkAccKeyOutput(info)
out, err := keyring.MkAccKeyOutput(k)
if err != nil {
return err
}

View File

@ -16,6 +16,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/testutil"
sdk "github.com/cosmos/cosmos-sdk/types"
)
@ -42,7 +43,8 @@ func Test_runAddCmdLedgerWithCustomCoinType(t *testing.T) {
// Prepare a keybase
kbHome := t.TempDir()
clientCtx := client.Context{}.WithKeyringDir(kbHome)
cdc := simapp.MakeTestEncodingConfig().Codec
clientCtx := client.Context{}.WithKeyringDir(kbHome).WithCodec(cdc)
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
cmd.SetArgs([]string{
@ -61,7 +63,7 @@ func Test_runAddCmdLedgerWithCustomCoinType(t *testing.T) {
require.NoError(t, cmd.ExecuteContext(ctx))
// Now check that it has been stored properly
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn)
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn, cdc)
require.NoError(t, err)
require.NotNil(t, kb)
t.Cleanup(func() {
@ -72,11 +74,13 @@ func Test_runAddCmdLedgerWithCustomCoinType(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, key1)
require.Equal(t, "keyname1", key1.GetName())
require.Equal(t, "keyname1", key1.Name)
require.Equal(t, keyring.TypeLedger, key1.GetType())
pub, err := key1.GetPubKey()
require.NoError(t, err)
require.Equal(t,
"PubKeySecp256k1{03028F0D5A9FD41600191CDEFDEA05E77A68DFBCE286241C0190805B9346667D07}",
key1.GetPubKey().String())
pub.String())
config.SetPurpose(44)
config.SetCoinType(118)
@ -91,8 +95,9 @@ func Test_runAddCmdLedger(t *testing.T) {
mockIn := testutil.ApplyMockIODiscardOutErr(cmd)
kbHome := t.TempDir()
encCfg := simapp.MakeTestEncodingConfig()
clientCtx := client.Context{}.WithKeyringDir(kbHome)
clientCtx := client.Context{}.WithKeyringDir(kbHome).WithCodec(encCfg.Codec)
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
cmd.SetArgs([]string{
@ -108,8 +113,10 @@ func Test_runAddCmdLedger(t *testing.T) {
require.NoError(t, cmd.ExecuteContext(ctx))
// Now check that it has been stored properly
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn)
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn, encCfg.Codec)
require.NoError(t, err)
// Now check that it has been stored properly
require.NotNil(t, kb)
t.Cleanup(func() {
_ = kb.Delete("keyname1")
@ -120,14 +127,16 @@ func Test_runAddCmdLedger(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, key1)
require.Equal(t, "keyname1", key1.GetName())
require.Equal(t, keyring.TypeLedger, key1.GetType())
require.Equal(t, "keyname1", key1.Name)
pub, err := key1.GetPubKey()
require.NoError(t, err)
require.Equal(t,
"PubKeySecp256k1{034FEF9CD7C4C63588D3B03FEB5281B9D232CBA34D6F3D71AEE59211FFBFE1FE87}",
key1.GetPubKey().String())
pub.String())
}
func Test_runAddCmdLedgerDryRun(t *testing.T) {
cdc := simapp.MakeTestEncodingConfig().Codec
testData := []struct {
name string
args []string
@ -152,6 +161,7 @@ func Test_runAddCmdLedgerDryRun(t *testing.T) {
added: false,
},
}
for _, tt := range testData {
tt := tt
t.Run(tt.name, func(t *testing.T) {
@ -160,14 +170,14 @@ func Test_runAddCmdLedgerDryRun(t *testing.T) {
kbHome := t.TempDir()
mockIn := testutil.ApplyMockIODiscardOutErr(cmd)
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn)
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn, cdc)
require.NoError(t, err)
clientCtx := client.Context{}.
WithKeyringDir(kbHome).
WithKeyring(kb)
WithKeyring(kb).
WithCodec(cdc)
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
b := bytes.NewBufferString("")
cmd.SetOut(b)
@ -184,7 +194,7 @@ func Test_runAddCmdLedgerDryRun(t *testing.T) {
} else {
_, err = kb.Key("testkey")
require.Error(t, err)
require.Equal(t, "testkey.info: key not found", err.Error())
require.Equal(t, "testkey: key not found", err.Error())
}
})
}

View File

@ -28,10 +28,12 @@ func Test_runAddCmdBasic(t *testing.T) {
mockIn := testutil.ApplyMockIODiscardOutErr(cmd)
kbHome := t.TempDir()
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn)
cdc := simapp.MakeTestEncodingConfig().Codec
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn, cdc)
require.NoError(t, err)
clientCtx := client.Context{}.WithKeyringDir(kbHome).WithInput(mockIn)
clientCtx := client.Context{}.WithKeyringDir(kbHome).WithInput(mockIn).WithCodec(cdc)
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
t.Cleanup(func() {
@ -122,6 +124,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"}`
cdc := simapp.MakeTestEncodingConfig().Codec
testData := []struct {
name string
@ -189,12 +192,12 @@ func Test_runAddCmdDryRun(t *testing.T) {
kbHome := t.TempDir()
mockIn := testutil.ApplyMockIODiscardOutErr(cmd)
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn)
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn, cdc)
require.NoError(t, err)
appCodec := simapp.MakeTestEncodingConfig().Codec
clientCtx := client.Context{}.
WithCodec(appCodec).
WithCodec(cdc).
WithKeyringDir(kbHome).
WithKeyring(kb)
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
@ -214,7 +217,7 @@ func Test_runAddCmdDryRun(t *testing.T) {
require.NoError(t, cmd.ExecuteContext(ctx))
if tt.added {
_, err = kb.Key("testkey")
_, err := kb.Key("testkey")
require.NoError(t, err)
out, err := ioutil.ReadAll(b)
@ -223,7 +226,7 @@ func Test_runAddCmdDryRun(t *testing.T) {
} else {
_, err = kb.Key("testkey")
require.Error(t, err)
require.Equal(t, "testkey.info: key not found", err.Error())
require.Equal(t, "testkey: key not found", err.Error())
}
})
}
@ -232,11 +235,12 @@ func Test_runAddCmdDryRun(t *testing.T) {
func TestAddRecoverFileBackend(t *testing.T) {
cmd := AddKeyCommand()
cmd.Flags().AddFlagSet(Commands("home").PersistentFlags())
cdc := simapp.MakeTestEncodingConfig().Codec
mockIn := testutil.ApplyMockIODiscardOutErr(cmd)
kbHome := t.TempDir()
clientCtx := client.Context{}.WithKeyringDir(kbHome).WithInput(mockIn)
clientCtx := client.Context{}.WithKeyringDir(kbHome).WithInput(mockIn).WithCodec(cdc)
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
cmd.SetArgs([]string{
@ -259,7 +263,7 @@ func TestAddRecoverFileBackend(t *testing.T) {
mockIn.Reset(fmt.Sprintf("%s\n%s\n%s\n", mnemonic, keyringPassword, keyringPassword))
require.NoError(t, cmd.ExecuteContext(ctx))
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendFile, kbHome, mockIn)
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendFile, kbHome, mockIn, cdc)
require.NoError(t, err)
t.Cleanup(func() {
@ -268,7 +272,7 @@ func TestAddRecoverFileBackend(t *testing.T) {
})
mockIn.Reset(fmt.Sprintf("%s\n%s\n", keyringPassword, keyringPassword))
info, err := kb.Key("keyname1")
k, err := kb.Key("keyname1")
require.NoError(t, err)
require.Equal(t, "keyname1", info.GetName())
require.Equal(t, "keyname1", k.Name)
}

View File

@ -35,7 +35,7 @@ private keys stored in a ledger device cannot be deleted with the CLI.
}
for _, name := range args {
info, err := clientCtx.Keyring.Key(name)
k, err := clientCtx.Keyring.Key(name)
if err != nil {
return err
}
@ -53,7 +53,7 @@ private keys stored in a ledger device cannot be deleted with the CLI.
return err
}
if info.GetType() == keyring.TypeLedger || info.GetType() == keyring.TypeOffline {
if k.GetType() == keyring.TypeLedger || k.GetType() == keyring.TypeOffline {
cmd.PrintErrln("Public key reference deleted")
continue
}

View File

@ -11,6 +11,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/testutil"
sdk "github.com/cosmos/cosmos-sdk/types"
)
@ -32,9 +33,10 @@ func Test_runDeleteCmd(t *testing.T) {
fakeKeyName2 := "runDeleteCmd_Key2"
path := sdk.GetConfig().GetFullBIP44Path()
cdc := simapp.MakeTestEncodingConfig().Codec
cmd.SetArgs([]string{"blah", fmt.Sprintf("--%s=%s", flags.FlagHome, kbHome)})
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn)
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn, cdc)
require.NoError(t, err)
_, err = kb.NewAccount(fakeKeyName1, testutil.TestMnemonic, "", path, hd.Secp256k1)
@ -45,13 +47,13 @@ func Test_runDeleteCmd(t *testing.T) {
clientCtx := client.Context{}.
WithKeyringDir(kbHome).
WithKeyring(kb)
WithCodec(cdc)
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
err = cmd.ExecuteContext(ctx)
require.Error(t, err)
require.EqualError(t, err, "blah.info: key not found")
require.EqualError(t, err, "blah: key not found")
// User confirmation missing
cmd.SetArgs([]string{

View File

@ -14,10 +14,12 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
)
func Test_runExportCmd(t *testing.T) {
cdc := simapp.MakeTestEncodingConfig().Codec
testCases := []struct {
name string
keyringBackend string
@ -84,7 +86,7 @@ func Test_runExportCmd(t *testing.T) {
mockInBuf := bufio.NewReader(mockIn)
// create a key
kb, err := keyring.New(sdk.KeyringServiceName(), tc.keyringBackend, kbHome, bufio.NewReader(mockInBuf))
kb, err := keyring.New(sdk.KeyringServiceName(), tc.keyringBackend, kbHome, bufio.NewReader(mockInBuf), cdc)
require.NoError(t, err)
t.Cleanup(func() {
kb.Delete("keyname1") // nolint:errcheck
@ -97,7 +99,8 @@ func Test_runExportCmd(t *testing.T) {
clientCtx := client.Context{}.
WithKeyringDir(kbHome).
WithKeyring(kb).
WithInput(mockInBuf)
WithInput(mockInBuf).
WithCodec(cdc)
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
err = cmd.ExecuteContext(ctx)

View File

@ -13,11 +13,13 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/testutil"
sdk "github.com/cosmos/cosmos-sdk/types"
)
func Test_runImportCmd(t *testing.T) {
cdc := simapp.MakeTestEncodingConfig().Codec
testCases := []struct {
name string
keyringBackend string
@ -80,15 +82,16 @@ HbP+c6JmeJy9JXe2rbbF1QtCX1gLqGcDQPBXiCtFvP7/8wTZtVOPj8vREzhZ9ElO
// Now add a temporary keybase
kbHome := t.TempDir()
kb, err := keyring.New(sdk.KeyringServiceName(), tc.keyringBackend, kbHome, nil)
kb, err := keyring.New(sdk.KeyringServiceName(), tc.keyringBackend, kbHome, nil, cdc)
require.NoError(t, err)
clientCtx := client.Context{}.
WithKeyringDir(kbHome).
WithKeyring(kb).
WithInput(mockIn)
WithInput(mockIn).
WithCodec(cdc)
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
require.NoError(t, err)
t.Cleanup(func() {
kb.Delete("keyname1") // nolint:errcheck
})

View File

@ -28,18 +28,18 @@ func runListCmd(cmd *cobra.Command, _ []string) error {
return err
}
infos, err := clientCtx.Keyring.List()
records, err := clientCtx.Keyring.List()
if err != nil {
return err
}
if ok, _ := cmd.Flags().GetBool(flagListNames); !ok {
printInfos(cmd.OutOrStdout(), infos, clientCtx.OutputFormat)
printKeyringRecords(cmd.OutOrStdout(), records, clientCtx.OutputFormat)
return nil
}
for _, info := range infos {
cmd.Println(info.GetName())
for _, k := range records {
cmd.Println(k.Name)
}
return nil

View File

@ -12,6 +12,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/testutil"
sdk "github.com/cosmos/cosmos-sdk/types"
)
@ -24,7 +25,8 @@ func Test_runListCmd(t *testing.T) {
kbHome2 := t.TempDir()
mockIn := testutil.ApplyMockIODiscardOutErr(cmd)
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome2, mockIn)
encCfg := simapp.MakeTestEncodingConfig()
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome2, mockIn, encCfg.Codec)
require.NoError(t, err)
clientCtx := client.Context{}.WithKeyring(kb)

View File

@ -1,147 +1,43 @@
package keys
import (
"bufio"
"fmt"
"io/ioutil"
"os"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/input"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/client"
)
// migratePassphrase is used as a no-op migration key passphrase as a passphrase
// is not needed for importing into the Keyring keystore.
const migratePassphrase = "NOOP_PASSPHRASE"
// MigrateCommand migrates key information from legacy keybase to OS secret store.
func MigrateCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "migrate <old_home_dir>",
Short: "Migrate keys from the legacy (db-based) Keybase",
Long: `Migrate key information from the legacy (db-based) Keybase to the new keyring-based Keyring.
The legacy Keybase used to persist keys in a LevelDB database stored in a 'keys' sub-directory of
the old client application's home directory, e.g. $HOME/.gaiacli/keys/.
For each key material entry, the command will prompt if the key should be skipped or not. If the key
is not to be skipped, the passphrase must be entered. The key will only be migrated if the passphrase
is correct. Otherwise, the command will exit and migration must be repeated.
Use: "migrate",
Short: "Migrate keys from amino to proto serialization format",
Long: `Migrate keys from Amino to Protocol Buffers records.
For each key material entry, the command will check if the key can be deserialized using proto.
If this is the case, the key is already migrated. Therefore, we skip it and continue with a next one.
Otherwise, we try to deserialize it using Amino into LegacyInfo. If this attempt is successful, we serialize
LegacyInfo to Protobuf serialization format and overwrite the keyring entry. If any error occurred, it will be
outputted in CLI and migration will be continued until all keys in the keyring DB are exhausted.
See https://github.com/cosmos/cosmos-sdk/pull/9695 for more details.
It is recommended to run in 'dry-run' mode first to verify all key migration material.
`,
Args: cobra.ExactArgs(1),
Args: cobra.NoArgs,
RunE: runMigrateCmd,
}
cmd.Flags().Bool(flags.FlagDryRun, false, "Run migration without actually persisting any changes to the new Keybase")
return cmd
}
func runMigrateCmd(cmd *cobra.Command, args []string) error {
rootDir, _ := cmd.Flags().GetString(flags.FlagHome)
// instantiate legacy keybase
var legacyKb keyring.LegacyKeybase
legacyKb, err := NewLegacyKeyBaseFromDir(args[0])
func runMigrateCmd(cmd *cobra.Command, _ []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
defer func() { _ = legacyKb.Close() }()
// fetch list of keys from legacy keybase
oldKeys, err := legacyKb.List()
if err != nil {
if _, err = clientCtx.Keyring.MigrateAll(); err != nil {
return err
}
buf := bufio.NewReader(cmd.InOrStdin())
keyringServiceName := sdk.KeyringServiceName()
var (
tmpDir string
migrator keyring.Importer
)
if dryRun, _ := cmd.Flags().GetBool(flags.FlagDryRun); dryRun {
tmpDir, err = ioutil.TempDir("", "migrator-migrate-dryrun")
if err != nil {
return errors.Wrap(err, "failed to create temporary directory for dryrun migration")
}
defer func() { _ = os.RemoveAll(tmpDir) }()
migrator, err = keyring.New(keyringServiceName, keyring.BackendTest, tmpDir, buf)
} else {
backend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
migrator, err = keyring.New(keyringServiceName, backend, rootDir, buf)
}
if err != nil {
return errors.Wrap(err, fmt.Sprintf(
"failed to initialize keybase for service %s at directory %s",
keyringServiceName, rootDir,
))
}
if len(oldKeys) == 0 {
cmd.PrintErrln("Migration Aborted: no keys to migrate")
return nil
}
for _, oldInfo := range oldKeys {
keyName := oldInfo.GetName()
keyType := oldInfo.GetType()
cmd.PrintErrf("Migrating key: '%s (%s)' ...\n", keyName, keyType)
// allow user to skip migrating specific keys
ok, err := input.GetConfirmation("Skip key migration?", buf, cmd.ErrOrStderr())
if err != nil {
return err
}
if ok {
continue
}
// TypeLocal needs an additional step to ask password.
// The other keyring types are handled by ImportInfo.
if keyType != keyring.TypeLocal {
infoImporter, ok := migrator.(keyring.LegacyInfoImporter)
if !ok {
return fmt.Errorf("the Keyring implementation does not support import operations of Info types")
}
if err = infoImporter.ImportInfo(oldInfo); err != nil {
return err
}
continue
}
password, err := input.GetPassword("Enter passphrase to decrypt key:", buf)
if err != nil {
return err
}
// NOTE: A passphrase is not actually needed here as when the key information
// is imported into the Keyring-based Keybase it only needs the password
// (see: writeLocalKey).
armoredPriv, err := legacyKb.ExportPrivKey(keyName, password, migratePassphrase)
if err != nil {
return err
}
if err := migrator.ImportPrivKey(keyName, armoredPriv, migratePassphrase); err != nil {
return err
}
}
cmd.PrintErrln("Migration complete.")
return err
cmd.Println("Keys migration has been successfully executed")
return nil
}

View File

@ -3,40 +3,152 @@ package keys
import (
"context"
"fmt"
"strings"
"testing"
design99keyring "github.com/99designs/keyring"
"github.com/stretchr/testify/suite"
"github.com/cosmos/cosmos-sdk/client"
"github.com/stretchr/testify/require"
"github.com/otiai10/copy"
"github.com/stretchr/testify/assert"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/testutil"
)
func Test_runMigrateCmd(t *testing.T) {
kbHome := t.TempDir()
clientCtx := client.Context{}.WithKeyringDir(kbHome)
type setter interface {
SetItem(item design99keyring.Item) error
}
type MigrateTestSuite struct {
suite.Suite
dir string
appName string
cdc codec.Codec
priv cryptotypes.PrivKey
pub cryptotypes.PubKey
}
func (s *MigrateTestSuite) SetupSuite() {
s.dir = s.T().TempDir()
s.cdc = simapp.MakeTestEncodingConfig().Codec
s.appName = "cosmos"
s.priv = cryptotypes.PrivKey(secp256k1.GenPrivKey())
s.pub = s.priv.PubKey()
}
func (s *MigrateTestSuite) Test_runListAndShowCmd() {
// adding LegacyInfo item into keyring
multi := multisig.NewLegacyAminoPubKey(
1, []cryptotypes.PubKey{
s.pub,
},
)
legacyMultiInfo, err := keyring.NewLegacyMultiInfo(s.appName, multi)
s.Require().NoError(err)
serializedLegacyMultiInfo := keyring.MarshalInfo(legacyMultiInfo)
item := design99keyring.Item{
Key: s.appName,
Data: serializedLegacyMultiInfo,
Description: "SDK kerying version",
}
//run test simd keys list - to see that the migrated key is there
cmd := ListKeysCmd()
cmd.Flags().AddFlagSet(Commands("home").PersistentFlags())
mockIn := testutil.ApplyMockIODiscardOutErr(cmd)
kb, err := keyring.New(s.appName, keyring.BackendTest, s.dir, mockIn, s.cdc)
s.Require().NoError(err)
setter, ok := kb.(setter)
s.Require().True(ok)
s.Require().NoError(setter.SetItem(item))
clientCtx := client.Context{}.WithKeyring(kb)
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
require.NoError(t, copy.Copy("testdata", kbHome))
cmd := MigrateCommand()
cmd.Flags().AddFlagSet(Commands("home").PersistentFlags())
//mockIn := testutil.ApplyMockIODiscardOutErr(cmd)
mockIn, mockOut := testutil.ApplyMockIO(cmd)
cmd.SetArgs([]string{
kbHome,
//fmt.Sprintf("--%s=%s", flags.FlagHome, kbHome),
fmt.Sprintf("--%s=true", flags.FlagDryRun),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
fmt.Sprintf("--%s=%s", flags.FlagHome, s.dir),
fmt.Sprintf("--%s=false", flagListNames),
})
mockIn.Reset("\n12345678\n\n\n\n\n")
t.Log(mockOut.String())
assert.NoError(t, cmd.ExecuteContext(ctx))
s.Require().NoError(cmd.ExecuteContext(ctx))
// simd show n1 - to see that the migration worked
cmd = ShowKeysCmd()
cmd.SetArgs([]string{s.appName})
clientCtx = clientCtx.WithCodec(s.cdc)
ctx = context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
s.Require().NoError(cmd.ExecuteContext(ctx))
}
func (s *MigrateTestSuite) Test_runMigrateCmdRecord() {
k, err := keyring.NewLocalRecord("test record", s.priv, s.pub)
s.Require().NoError(err)
serializedRecord, err := s.cdc.Marshal(k)
s.Require().NoError(err)
item := design99keyring.Item{
Key: s.appName,
Data: serializedRecord,
Description: "SDK kerying version",
}
cmd := MigrateCommand()
mockIn := strings.NewReader("")
kb, err := keyring.New(s.appName, keyring.BackendTest, s.dir, mockIn, s.cdc)
s.Require().NoError(err)
setter, ok := kb.(setter)
s.Require().True(ok)
s.Require().NoError(setter.SetItem(item))
clientCtx := client.Context{}.WithKeyring(kb)
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
s.Require().NoError(cmd.ExecuteContext(ctx))
}
func (s *MigrateTestSuite) Test_runMigrateCmdLegacyMultiInfo() {
// adding LegacyInfo item into keyring
multi := multisig.NewLegacyAminoPubKey(
1, []cryptotypes.PubKey{
s.pub,
},
)
legacyMultiInfo, err := keyring.NewLegacyMultiInfo(s.appName, multi)
s.Require().NoError(err)
serializedLegacyMultiInfo := keyring.MarshalInfo(legacyMultiInfo)
item := design99keyring.Item{
Key: s.appName,
Data: serializedLegacyMultiInfo,
Description: "SDK kerying version",
}
cmd := MigrateCommand()
mockIn := testutil.ApplyMockIODiscardOutErr(cmd)
kb, err := keyring.New(s.appName, keyring.BackendTest, s.dir, mockIn, s.cdc)
s.Require().NoError(err)
setter, ok := kb.(setter)
s.Require().True(ok)
s.Require().NoError(setter.SetItem(item))
clientCtx := client.Context{}.WithKeyring(kb)
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
s.Require().NoError(cmd.ExecuteContext(ctx))
}
func TestMigrateTestSuite(t *testing.T) {
suite.Run(t, new(MigrateTestSuite))
}

View File

@ -5,7 +5,7 @@ import (
"crypto/sha256"
"fmt"
bip39 "github.com/cosmos/go-bip39"
"github.com/cosmos/go-bip39"
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client/input"

View File

@ -31,7 +31,7 @@ private keys stored in a ledger device cannot be renamed with the CLI.
oldName, newName := args[0], args[1]
info, err := clientCtx.Keyring.Key(oldName)
k, err := clientCtx.Keyring.Key(oldName)
if err != nil {
return err
}
@ -50,7 +50,7 @@ private keys stored in a ledger device cannot be renamed with the CLI.
return err
}
if info.GetType() == keyring.TypeLedger || info.GetType() == keyring.TypeOffline {
if k.GetType() == keyring.TypeLedger || k.GetType() == keyring.TypeOffline {
cmd.PrintErrln("Public key reference renamed")
return nil
}

View File

@ -11,6 +11,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/testutil"
sdk "github.com/cosmos/cosmos-sdk/types"
)
@ -30,7 +31,8 @@ func Test_runRenameCmd(t *testing.T) {
path := sdk.GetConfig().GetFullBIP44Path()
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn)
cdc := simapp.MakeTestEncodingConfig().Codec
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn, cdc)
require.NoError(t, err)
// put fakeKeyName1 in keyring
@ -39,7 +41,7 @@ func Test_runRenameCmd(t *testing.T) {
clientCtx := client.Context{}.
WithKeyringDir(kbHome).
WithKeyring(kb)
WithCodec(cdc)
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
@ -47,7 +49,7 @@ func Test_runRenameCmd(t *testing.T) {
cmd.SetArgs([]string{"blah", "blaah", fmt.Sprintf("--%s=%s", flags.FlagHome, kbHome)})
err = cmd.ExecuteContext(ctx)
require.Error(t, err)
require.EqualError(t, err, "blah.info: key not found")
require.EqualError(t, err, "blah: key not found")
// User confirmation missing
cmd.SetArgs([]string{
@ -80,11 +82,18 @@ func Test_runRenameCmd(t *testing.T) {
// key2 exists now
renamedKey, err := kb.Key(fakeKeyName2)
require.NoError(t, err)
require.Equal(t, oldKey.GetPubKey(), renamedKey.GetPubKey())
oldPk, err := oldKey.GetPubKey()
require.NoError(t, err)
renamedPk, err := renamedKey.GetPubKey()
require.NoError(t, err)
require.Equal(t, oldPk, renamedPk)
require.Equal(t, oldKey.GetType(), renamedKey.GetType())
require.Equal(t, oldKey.GetAddress(), renamedKey.GetAddress())
require.Equal(t, oldKey.GetAlgo(), renamedKey.GetAlgo())
oldAddr, err := oldKey.GetAddress()
require.NoError(t, err)
renamedAddr, err := renamedKey.GetAddress()
require.NoError(t, err)
require.Equal(t, oldAddr, renamedAddr)
// try to rename key1 but it doesnt exist anymore so error
cmd.SetArgs([]string{

View File

@ -27,8 +27,6 @@ const (
FlagDevice = "device"
flagMultiSigThreshold = "multisig-threshold"
defaultMultiSigKeyName = "multi"
)
// ShowKeysCmd shows key information for a given key name.
@ -53,36 +51,40 @@ consisting of all the keys provided by name and multisig threshold.`,
}
func runShowCmd(cmd *cobra.Command, args []string) (err error) {
var info keyring.Info
k := new(keyring.Record)
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
outputFormat := clientCtx.OutputFormat
if len(args) == 1 {
info, err = fetchKey(clientCtx.Keyring, args[0])
k, err = fetchKey(clientCtx.Keyring, args[0])
if err != nil {
return fmt.Errorf("%s is not a valid name or address: %v", args[0], err)
}
} else {
pks := make([]cryptotypes.PubKey, len(args))
for i, keyref := range args {
info, err := fetchKey(clientCtx.Keyring, keyref)
k, err := fetchKey(clientCtx.Keyring, keyref)
if err != nil {
return fmt.Errorf("%s is not a valid name or address: %v", keyref, err)
}
pks[i] = info.GetPubKey()
key, err := k.GetPubKey()
if err != nil {
return err
}
pks[i] = key
}
multisigThreshold, _ := cmd.Flags().GetInt(flagMultiSigThreshold)
err = validateMultisigThreshold(multisigThreshold, len(args))
if err != nil {
if err := validateMultisigThreshold(multisigThreshold, len(args)); err != nil {
return err
}
multikey := multisig.NewLegacyAminoPubKey(multisigThreshold, pks)
info, err = keyring.NewMultiInfo(defaultMultiSigKeyName, multikey)
k, err = keyring.NewMultiRecord(k.Name, multikey)
if err != nil {
return err
}
@ -118,7 +120,7 @@ func runShowCmd(cmd *cobra.Command, args []string) (err error) {
switch {
case isShowAddr, isShowPubKey:
ko, err := bechKeyOut(info)
ko, err := bechKeyOut(k)
if err != nil {
return err
}
@ -128,7 +130,7 @@ func runShowCmd(cmd *cobra.Command, args []string) (err error) {
}
fmt.Fprintln(cmd.OutOrStdout(), out)
default:
printKeyInfo(cmd.OutOrStdout(), info, bechKeyOut, clientCtx.OutputFormat)
printKeyringRecord(cmd.OutOrStdout(), k, bechKeyOut, outputFormat)
}
if isShowDevice {
@ -140,36 +142,43 @@ func runShowCmd(cmd *cobra.Command, args []string) (err error) {
}
// Override and show in the device
if info.GetType() != keyring.TypeLedger {
if k.GetType() != keyring.TypeLedger {
return fmt.Errorf("the device flag (-d) can only be used for accounts stored in devices")
}
hdpath, err := info.GetPath()
if err != nil {
return nil
ledgerItem := k.GetLedger()
if ledgerItem == nil {
return errors.New("unable to get ledger item")
}
return ledger.ShowAddress(*hdpath, info.GetPubKey(), sdk.GetConfig().GetBech32AccountAddrPrefix())
pk, err := k.GetPubKey()
if err != nil {
return err
}
return ledger.ShowAddress(*ledgerItem.Path, pk, sdk.GetConfig().GetBech32AccountAddrPrefix())
}
return nil
}
func fetchKey(kb keyring.Keyring, keyref string) (keyring.Info, error) {
func fetchKey(kb keyring.Keyring, keyref string) (*keyring.Record, error) {
// firstly check if the keyref is a key name of a key registered in a keyring.
info, err := kb.Key(keyref)
k, err := kb.Key(keyref)
// if the key is not there or if we have a problem with a keyring itself then we move to a
// fallback: searching for key by address.
if err == nil || !sdkerr.IsOf(err, sdkerr.ErrIO, sdkerr.ErrKeyNotFound) {
return info, err
}
accAddr, err := sdk.AccAddressFromBech32(keyref)
if err != nil {
return info, err
return k, err
}
info, err = kb.KeyByAddress(accAddr)
return info, sdkerr.Wrap(err, "Invalid key")
accAddr, err := sdk.AccAddressFromBech32(keyref)
if err != nil {
return k, err
}
k, err = kb.KeyByAddress(accAddr)
return k, sdkerr.Wrap(err, "Invalid key")
}
func validateMultisigThreshold(k, nKeys int) error {

View File

@ -14,6 +14,7 @@ import (
"github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/testutil"
sdk "github.com/cosmos/cosmos-sdk/types"
)
@ -24,12 +25,18 @@ func Test_multiSigKey_Properties(t *testing.T) {
1,
[]cryptotypes.PubKey{tmpKey1.PubKey()},
)
tmp, err := keyring.NewMultiInfo("myMultisig", pk)
k, err := keyring.NewMultiRecord("myMultisig", pk)
require.NoError(t, err)
require.Equal(t, "myMultisig", tmp.GetName())
require.Equal(t, keyring.TypeMulti, tmp.GetType())
require.Equal(t, "D3923267FA8A3DD367BB768FA8BDC8FF7F89DA3F", tmp.GetPubKey().Address().String())
require.Equal(t, "cosmos16wfryel63g7axeamw68630wglalcnk3l0zuadc", sdk.MustBech32ifyAddressBytes("cosmos", tmp.GetAddress()))
require.Equal(t, "myMultisig", k.Name)
require.Equal(t, keyring.TypeMulti, k.GetType())
pub, err := k.GetPubKey()
require.NoError(t, err)
require.Equal(t, "D3923267FA8A3DD367BB768FA8BDC8FF7F89DA3F", pub.Address().String())
addr, err := k.GetAddress()
require.NoError(t, err)
require.Equal(t, "cosmos16wfryel63g7axeamw68630wglalcnk3l0zuadc", sdk.MustBech32ifyAddressBytes("cosmos", addr))
}
func Test_showKeysCmd(t *testing.T) {
@ -45,12 +52,13 @@ func Test_runShowCmd(t *testing.T) {
mockIn := testutil.ApplyMockIODiscardOutErr(cmd)
kbHome := t.TempDir()
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn)
cdc := simapp.MakeTestEncodingConfig().Codec
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn, cdc)
require.NoError(t, err)
clientCtx := client.Context{}.
WithKeyringDir(kbHome).
WithKeyring(kb)
WithCodec(cdc)
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
cmd.SetArgs([]string{"invalid"})
@ -79,49 +87,51 @@ func Test_runShowCmd(t *testing.T) {
cmd.SetArgs([]string{
fakeKeyName1,
fmt.Sprintf("--%s=%s", flags.FlagHome, kbHome),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
fmt.Sprintf("--%s=", FlagBechPrefix),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
})
require.EqualError(t, cmd.ExecuteContext(ctx), "invalid Bech32 prefix encoding provided: ")
cmd.SetArgs([]string{
fakeKeyName1,
fmt.Sprintf("--%s=%s", flags.FlagHome, kbHome),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
fmt.Sprintf("--%s=%s", FlagBechPrefix, sdk.PrefixAccount),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
})
// try fetch by name
require.NoError(t, cmd.ExecuteContext(ctx))
// try fetch by addr
info, err := kb.Key(fakeKeyName1)
k, err := kb.Key(fakeKeyName1)
require.NoError(t, err)
addr, err := k.GetAddress()
require.NoError(t, err)
cmd.SetArgs([]string{
info.GetAddress().String(),
addr.String(),
fmt.Sprintf("--%s=%s", flags.FlagHome, kbHome),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
fmt.Sprintf("--%s=%s", FlagBechPrefix, sdk.PrefixAccount),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
})
require.NoError(t, err)
require.NoError(t, cmd.ExecuteContext(ctx))
// Now try multisig key - set bech to acc
cmd.SetArgs([]string{
fakeKeyName1, fakeKeyName2,
fmt.Sprintf("--%s=%s", flags.FlagHome, kbHome),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
fmt.Sprintf("--%s=%s", FlagBechPrefix, sdk.PrefixAccount),
fmt.Sprintf("--%s=0", flagMultiSigThreshold),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
})
require.EqualError(t, cmd.ExecuteContext(ctx), "threshold must be a positive integer")
cmd.SetArgs([]string{
fakeKeyName1, fakeKeyName2,
fmt.Sprintf("--%s=%s", flags.FlagHome, kbHome),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
fmt.Sprintf("--%s=%s", FlagBechPrefix, sdk.PrefixAccount),
fmt.Sprintf("--%s=2", flagMultiSigThreshold),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
})
require.NoError(t, cmd.ExecuteContext(ctx))
@ -129,31 +139,31 @@ func Test_runShowCmd(t *testing.T) {
cmd.SetArgs([]string{
fakeKeyName1, fakeKeyName2,
fmt.Sprintf("--%s=%s", flags.FlagHome, kbHome),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
fmt.Sprintf("--%s=acc", FlagBechPrefix),
fmt.Sprintf("--%s=true", FlagDevice),
fmt.Sprintf("--%s=2", flagMultiSigThreshold),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
})
require.EqualError(t, cmd.ExecuteContext(ctx), "the device flag (-d) can only be used for accounts stored in devices")
cmd.SetArgs([]string{
fakeKeyName1, fakeKeyName2,
fmt.Sprintf("--%s=%s", flags.FlagHome, kbHome),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
fmt.Sprintf("--%s=val", FlagBechPrefix),
fmt.Sprintf("--%s=true", FlagDevice),
fmt.Sprintf("--%s=2", flagMultiSigThreshold),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
})
require.EqualError(t, cmd.ExecuteContext(ctx), "the device flag (-d) can only be used for accounts")
cmd.SetArgs([]string{
fakeKeyName1, fakeKeyName2,
fmt.Sprintf("--%s=%s", flags.FlagHome, kbHome),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
fmt.Sprintf("--%s=val", FlagBechPrefix),
fmt.Sprintf("--%s=true", FlagDevice),
fmt.Sprintf("--%s=2", flagMultiSigThreshold),
fmt.Sprintf("--%s=true", FlagPublicKey),
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, keyring.BackendTest),
})
require.EqualError(t, cmd.ExecuteContext(ctx), "the device flag (-d) can only be used for addresses not pubkeys")
}

View File

@ -1,6 +1,6 @@
package keys
// used for outputting keyring.Info over REST
// used for outputting keyring.LegacyInfo over REST
// AddNewKey request a new key
type AddNewKey struct {

View File

@ -3,7 +3,6 @@ package keys
import (
"fmt"
"io"
"path/filepath"
yaml "gopkg.in/yaml.v2"
@ -14,32 +13,19 @@ import (
const (
OutputFormatText = "text"
OutputFormatJSON = "json"
// defaultKeyDBName is the client's subdirectory where keys are stored.
defaultKeyDBName = "keys"
)
type bechKeyOutFn func(keyInfo cryptokeyring.Info) (cryptokeyring.KeyOutput, error)
type bechKeyOutFn func(k *cryptokeyring.Record) (cryptokeyring.KeyOutput, error)
// NewLegacyKeyBaseFromDir initializes a legacy keybase at the rootDir directory. Keybase
// options can be applied when generating this new Keybase.
func NewLegacyKeyBaseFromDir(rootDir string, opts ...cryptokeyring.KeybaseOption) (cryptokeyring.LegacyKeybase, error) {
return getLegacyKeyBaseFromDir(rootDir, opts...)
}
func getLegacyKeyBaseFromDir(rootDir string, opts ...cryptokeyring.KeybaseOption) (cryptokeyring.LegacyKeybase, error) {
return cryptokeyring.NewLegacy(defaultKeyDBName, filepath.Join(rootDir, "keys"), opts...)
}
func printKeyInfo(w io.Writer, keyInfo cryptokeyring.Info, bechKeyOut bechKeyOutFn, output string) {
ko, err := bechKeyOut(keyInfo)
func printKeyringRecord(w io.Writer, k *cryptokeyring.Record, bechKeyOut bechKeyOutFn, output string) {
ko, err := bechKeyOut(k)
if err != nil {
panic(err)
}
switch output {
case OutputFormatText:
printTextInfos(w, []cryptokeyring.KeyOutput{ko})
printTextRecords(w, []cryptokeyring.KeyOutput{ko})
case OutputFormatJSON:
out, err := KeysCdc.MarshalJSON(ko)
@ -51,17 +37,19 @@ func printKeyInfo(w io.Writer, keyInfo cryptokeyring.Info, bechKeyOut bechKeyOut
}
}
func printInfos(w io.Writer, infos []cryptokeyring.Info, output string) {
kos, err := cryptokeyring.MkAccKeysOutput(infos)
func printKeyringRecords(w io.Writer, records []*cryptokeyring.Record, output string) {
kos, err := cryptokeyring.MkAccKeysOutput(records)
if err != nil {
panic(err)
}
switch output {
case OutputFormatText:
printTextInfos(w, kos)
printTextRecords(w, kos)
case OutputFormatJSON:
// TODO https://github.com/cosmos/cosmos-sdk/issues/8046
// Replace AminoCdc with Proto JSON
out, err := KeysCdc.MarshalJSON(kos)
if err != nil {
panic(err)
@ -71,10 +59,11 @@ func printInfos(w io.Writer, infos []cryptokeyring.Info, output string) {
}
}
func printTextInfos(w io.Writer, kos []cryptokeyring.KeyOutput) {
func printTextRecords(w io.Writer, kos []cryptokeyring.KeyOutput) {
out, err := yaml.Marshal(&kos)
if err != nil {
panic(err)
}
fmt.Fprintln(w, string(out))
}

View File

@ -197,12 +197,16 @@ func Sign(txf Factory, name string, txBuilder client.TxBuilder, overwriteSig boo
return err
}
key, err := txf.keybase.Key(name)
k, err := txf.keybase.Key(name)
if err != nil {
return err
}
pubKey, err := k.GetPubKey()
if err != nil {
return err
}
pubKey := key.GetPubKey()
pubkeys, err := txBuilder.GetTx().GetPubKeys()
if err != nil {
return err

View File

@ -134,24 +134,27 @@ func TestBuildUnsignedTx(t *testing.T) {
func TestSign(t *testing.T) {
requireT := require.New(t)
path := hd.CreateHDPath(118, 0, 0).String()
kr, err := keyring.New(t.Name(), "test", t.TempDir(), nil)
encCfg := simapp.MakeTestEncodingConfig()
kb, err := keyring.New(t.Name(), "test", t.TempDir(), nil, encCfg.Codec)
requireT.NoError(err)
var from1 = "test_key1"
var from2 = "test_key2"
// create a new key using a mnemonic generator and test if we can reuse seed to recreate that account
_, seed, err := kr.NewMnemonic(from1, keyring.English, path, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
_, seed, err := kb.NewMnemonic(from1, keyring.English, path, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
requireT.NoError(err)
requireT.NoError(kr.Delete(from1))
info1, _, err := kr.NewMnemonic(from1, keyring.English, path, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
requireT.NoError(kb.Delete(from1))
k1, _, err := kb.NewMnemonic(from1, keyring.English, path, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
requireT.NoError(err)
info2, err := kr.NewAccount(from2, seed, "", path, hd.Secp256k1)
k2, err := kb.NewAccount(from2, seed, "", path, hd.Secp256k1)
requireT.NoError(err)
pubKey1 := info1.GetPubKey()
pubKey2 := info2.GetPubKey()
pubKey1, err := k1.GetPubKey()
requireT.NoError(err)
pubKey2, err := k2.GetPubKey()
requireT.NoError(err)
requireT.NotEqual(pubKey1.Bytes(), pubKey2.Bytes())
t.Log("Pub keys:", pubKey1, pubKey2)
@ -163,12 +166,16 @@ func TestSign(t *testing.T) {
WithMemo("memo").
WithChainID("test-chain")
txfDirect := txfNoKeybase.
WithKeybase(kr).
WithKeybase(kb).
WithSignMode(signingtypes.SignMode_SIGN_MODE_DIRECT)
txfAmino := txfDirect.
WithSignMode(signingtypes.SignMode_SIGN_MODE_LEGACY_AMINO_JSON)
msg1 := banktypes.NewMsgSend(info1.GetAddress(), sdk.AccAddress("to"), nil)
msg2 := banktypes.NewMsgSend(info2.GetAddress(), sdk.AccAddress("to"), nil)
addr1, err := k1.GetAddress()
requireT.NoError(err)
addr2, err := k2.GetAddress()
requireT.NoError(err)
msg1 := banktypes.NewMsgSend(addr1, sdk.AccAddress("to"), nil)
msg2 := banktypes.NewMsgSend(addr2, sdk.AccAddress("to"), nil)
txb, err := txfNoKeybase.BuildUnsignedTx(msg1, msg2)
requireT.NoError(err)
txb2, err := txfNoKeybase.BuildUnsignedTx(msg1, msg2)

View File

@ -19,6 +19,7 @@ import (
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/types"
)
@ -70,26 +71,29 @@ func TestArmorUnarmorPrivKey(t *testing.T) {
func TestArmorUnarmorPubKey(t *testing.T) {
// Select the encryption and storage for your cryptostore
cstore := keyring.NewInMemory()
encCfg := simapp.MakeTestEncodingConfig()
cstore := keyring.NewInMemory(encCfg.Codec)
// Add keys and see they return in alphabetical order
info, _, err := cstore.NewMnemonic("Bob", keyring.English, types.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
k, _, err := cstore.NewMnemonic("Bob", keyring.English, types.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
require.NoError(t, err)
armored := crypto.ArmorPubKeyBytes(legacy.Cdc.Amino.MustMarshalBinaryBare(info.GetPubKey()), "")
key, err := k.GetPubKey()
require.NoError(t, err)
armored := crypto.ArmorPubKeyBytes(legacy.Cdc.Amino.MustMarshalBinaryBare(key), "")
pubBytes, algo, err := crypto.UnarmorPubKeyBytes(armored)
require.NoError(t, err)
pub, err := legacy.PubKeyFromBytes(pubBytes)
require.NoError(t, err)
require.Equal(t, string(hd.Secp256k1Type), algo)
require.True(t, pub.Equals(info.GetPubKey()))
require.True(t, pub.Equals(key))
armored = crypto.ArmorPubKeyBytes(legacy.Cdc.Amino.MustMarshalBinaryBare(info.GetPubKey()), "unknown")
armored = crypto.ArmorPubKeyBytes(legacy.Cdc.Amino.MustMarshalBinaryBare(key), "unknown")
pubBytes, algo, err = crypto.UnarmorPubKeyBytes(armored)
require.NoError(t, err)
pub, err = legacy.PubKeyFromBytes(pubBytes)
require.NoError(t, err)
require.Equal(t, "unknown", algo)
require.True(t, pub.Equals(info.GetPubKey()))
require.True(t, pub.Equals(key))
armored, err = cstore.ExportPrivKeyArmor("Bob", "passphrase")
require.NoError(t, err)

View File

@ -16,5 +16,10 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
registry.RegisterImplementations(pk, &ed25519.PubKey{})
registry.RegisterImplementations(pk, &secp256k1.PubKey{})
registry.RegisterImplementations(pk, &multisig.LegacyAminoPubKey{})
var priv *cryptotypes.PrivKey
registry.RegisterInterface("cosmos.crypto.PrivKey", priv)
registry.RegisterImplementations(priv, &secp256k1.PrivKey{})
registry.RegisterImplementations(priv, &ed25519.PrivKey{}) //nolint
secp256r1.RegisterInterfaces(registry)
}

View File

@ -1,7 +1,7 @@
package hd
import (
bip39 "github.com/cosmos/go-bip39"
"github.com/cosmos/go-bip39"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/crypto/types"

View File

@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/require"
bip39 "github.com/cosmos/go-bip39"
"github.com/cosmos/go-bip39"
"github.com/tendermint/tendermint/crypto"

422
crypto/hd/hd.pb.go Normal file
View File

@ -0,0 +1,422 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: cosmos/crypto/hd/v1/hd.proto
package hd
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// BIP44Params is used as path field in ledger item in Record.
type BIP44Params struct {
// purpose is a constant set to 44' (or 0x8000002C) following the BIP43 recommendation
Purpose uint32 `protobuf:"varint,1,opt,name=purpose,proto3" json:"purpose,omitempty"`
// coin_type is a constant that improves privacy
CoinType uint32 `protobuf:"varint,2,opt,name=coin_type,json=coinType,proto3" json:"coin_type,omitempty"`
// account splits the key space into independent user identities
Account uint32 `protobuf:"varint,3,opt,name=account,proto3" json:"account,omitempty"`
// change is a constant used for public derivation. Constant 0 is used for external chain and constant 1 for internal chain.
Change bool `protobuf:"varint,4,opt,name=change,proto3" json:"change,omitempty"`
// address_index is used as child index in BIP32 derivation
AddressIndex uint32 `protobuf:"varint,5,opt,name=address_index,json=addressIndex,proto3" json:"address_index,omitempty"`
}
func (m *BIP44Params) Reset() { *m = BIP44Params{} }
func (*BIP44Params) ProtoMessage() {}
func (*BIP44Params) Descriptor() ([]byte, []int) {
return fileDescriptor_cf10f1fb5e778a8d, []int{0}
}
func (m *BIP44Params) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *BIP44Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_BIP44Params.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *BIP44Params) XXX_Merge(src proto.Message) {
xxx_messageInfo_BIP44Params.Merge(m, src)
}
func (m *BIP44Params) XXX_Size() int {
return m.Size()
}
func (m *BIP44Params) XXX_DiscardUnknown() {
xxx_messageInfo_BIP44Params.DiscardUnknown(m)
}
var xxx_messageInfo_BIP44Params proto.InternalMessageInfo
func init() {
proto.RegisterType((*BIP44Params)(nil), "cosmos.crypto.hd.v1.BIP44Params")
}
func init() { proto.RegisterFile("cosmos/crypto/hd/v1/hd.proto", fileDescriptor_cf10f1fb5e778a8d) }
var fileDescriptor_cf10f1fb5e778a8d = []byte{
// 266 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x49, 0xce, 0x2f, 0xce,
0xcd, 0x2f, 0xd6, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0xcf, 0x48, 0xd1, 0x2f, 0x33, 0xd4,
0xcf, 0x48, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x86, 0xc8, 0xea, 0x41, 0x64, 0xf5,
0x32, 0x52, 0xf4, 0xca, 0x0c, 0xa5, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0xf2, 0xfa, 0x20, 0x16,
0x44, 0xa9, 0xd2, 0x42, 0x46, 0x2e, 0x6e, 0x27, 0xcf, 0x00, 0x13, 0x93, 0x80, 0xc4, 0xa2, 0xc4,
0xdc, 0x62, 0x21, 0x09, 0x2e, 0xf6, 0x82, 0xd2, 0xa2, 0x82, 0xfc, 0xe2, 0x54, 0x09, 0x46, 0x05,
0x46, 0x0d, 0xde, 0x20, 0x18, 0x57, 0x48, 0x9a, 0x8b, 0x33, 0x39, 0x3f, 0x33, 0x2f, 0xbe, 0xa4,
0xb2, 0x20, 0x55, 0x82, 0x09, 0x2c, 0xc7, 0x01, 0x12, 0x08, 0xa9, 0x2c, 0x48, 0x05, 0x69, 0x4b,
0x4c, 0x4e, 0xce, 0x2f, 0xcd, 0x2b, 0x91, 0x60, 0x86, 0x68, 0x83, 0x72, 0x85, 0xc4, 0xb8, 0xd8,
0x92, 0x33, 0x12, 0xf3, 0xd2, 0x53, 0x25, 0x58, 0x14, 0x18, 0x35, 0x38, 0x82, 0xa0, 0x3c, 0x21,
0x65, 0x2e, 0xde, 0xc4, 0x94, 0x94, 0xa2, 0xd4, 0xe2, 0xe2, 0xf8, 0xcc, 0xbc, 0x94, 0xd4, 0x0a,
0x09, 0x56, 0xb0, 0x3e, 0x1e, 0xa8, 0xa0, 0x27, 0x48, 0xcc, 0x8a, 0x65, 0xc6, 0x02, 0x79, 0x06,
0x27, 0x97, 0x13, 0x0f, 0xe5, 0x18, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1,
0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21,
0x4a, 0x2d, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0x1f, 0x16, 0x2a, 0x60,
0x4a, 0xb7, 0x38, 0x25, 0x1b, 0x11, 0x40, 0x49, 0x6c, 0x60, 0x0f, 0x1b, 0x03, 0x02, 0x00, 0x00,
0xff, 0xff, 0x31, 0xf6, 0x77, 0xe8, 0x3b, 0x01, 0x00, 0x00,
}
func (m *BIP44Params) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *BIP44Params) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *BIP44Params) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.AddressIndex != 0 {
i = encodeVarintHd(dAtA, i, uint64(m.AddressIndex))
i--
dAtA[i] = 0x28
}
if m.Change {
i--
if m.Change {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i--
dAtA[i] = 0x20
}
if m.Account != 0 {
i = encodeVarintHd(dAtA, i, uint64(m.Account))
i--
dAtA[i] = 0x18
}
if m.CoinType != 0 {
i = encodeVarintHd(dAtA, i, uint64(m.CoinType))
i--
dAtA[i] = 0x10
}
if m.Purpose != 0 {
i = encodeVarintHd(dAtA, i, uint64(m.Purpose))
i--
dAtA[i] = 0x8
}
return len(dAtA) - i, nil
}
func encodeVarintHd(dAtA []byte, offset int, v uint64) int {
offset -= sovHd(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *BIP44Params) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.Purpose != 0 {
n += 1 + sovHd(uint64(m.Purpose))
}
if m.CoinType != 0 {
n += 1 + sovHd(uint64(m.CoinType))
}
if m.Account != 0 {
n += 1 + sovHd(uint64(m.Account))
}
if m.Change {
n += 2
}
if m.AddressIndex != 0 {
n += 1 + sovHd(uint64(m.AddressIndex))
}
return n
}
func sovHd(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozHd(x uint64) (n int) {
return sovHd(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *BIP44Params) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowHd
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: BIP44Params: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: BIP44Params: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Purpose", wireType)
}
m.Purpose = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowHd
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Purpose |= uint32(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field CoinType", wireType)
}
m.CoinType = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowHd
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.CoinType |= uint32(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Account", wireType)
}
m.Account = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowHd
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Account |= uint32(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 4:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Change", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowHd
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
m.Change = bool(v != 0)
case 5:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field AddressIndex", wireType)
}
m.AddressIndex = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowHd
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.AddressIndex |= uint32(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipHd(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthHd
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipHd(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowHd
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowHd
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowHd
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthHd
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupHd
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthHd
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthHd = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowHd = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupHd = fmt.Errorf("proto: unexpected end of group")
)

View File

@ -13,18 +13,6 @@ import (
"github.com/btcsuite/btcd/btcec"
)
// BIP44Params wraps BIP 44 params (5 level BIP 32 path).
// To receive a canonical string representation ala
// m / purpose' / coinType' / account' / change / addressIndex
// call String() on a BIP44Params instance.
type BIP44Params struct {
Purpose uint32 `json:"purpose"`
CoinType uint32 `json:"coinType"`
Account uint32 `json:"account"`
Change bool `json:"change"`
AddressIndex uint32 `json:"addressIndex"`
}
// NewParams creates a BIP 44 parameter object from the params:
// m / purpose' / coinType' / account' / change / addressIndex
func NewParams(purpose, coinType, account uint32, change bool, addressIdx uint32) *BIP44Params {

View File

@ -8,7 +8,7 @@ import (
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/types"
bip39 "github.com/cosmos/go-bip39"
"github.com/cosmos/go-bip39"
"github.com/stretchr/testify/require"
)

View File

@ -12,10 +12,10 @@ func init() {
// RegisterLegacyAminoCodec registers concrete types and interfaces on the given codec.
func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
cdc.RegisterInterface((*Info)(nil), nil)
cdc.RegisterInterface((*LegacyInfo)(nil), nil)
cdc.RegisterConcrete(hd.BIP44Params{}, "crypto/keys/hd/BIP44Params", nil)
cdc.RegisterConcrete(localInfo{}, "crypto/keys/localInfo", nil)
cdc.RegisterConcrete(ledgerInfo{}, "crypto/keys/ledgerInfo", nil)
cdc.RegisterConcrete(offlineInfo{}, "crypto/keys/offlineInfo", nil)
cdc.RegisterConcrete(multiInfo{}, "crypto/keys/multiInfo", nil)
cdc.RegisterConcrete(legacyLocalInfo{}, "crypto/keys/localInfo", nil)
cdc.RegisterConcrete(legacyLedgerInfo{}, "crypto/keys/ledgerInfo", nil)
cdc.RegisterConcrete(legacyOfflineInfo{}, "crypto/keys/offlineInfo", nil)
cdc.RegisterConcrete(LegacyMultiInfo{}, "crypto/keys/multiInfo", nil)
}

View File

@ -12,13 +12,13 @@ import (
"strings"
"github.com/99designs/keyring"
bip39 "github.com/cosmos/go-bip39"
"github.com/cosmos/go-bip39"
"github.com/pkg/errors"
"github.com/tendermint/crypto/bcrypt"
tmcrypto "github.com/tendermint/tendermint/crypto"
"github.com/cosmos/cosmos-sdk/client/input"
"github.com/cosmos/cosmos-sdk/codec/legacy"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/crypto"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/ledger"
@ -54,14 +54,14 @@ var (
// Keyring exposes operations over a backend supported by github.com/99designs/keyring.
type Keyring interface {
// List all keys.
List() ([]Info, error)
List() ([]*Record, error)
// Supported signing algorithms for Keyring and Ledger respectively.
SupportedAlgorithms() (SigningAlgoList, SigningAlgoList)
// Key and KeyByAddress return keys by uid and address respectively.
Key(uid string) (Info, error)
KeyByAddress(address sdk.Address) (Info, error)
Key(uid string) (*Record, error)
KeyByAddress(address sdk.Address) (*Record, error)
// Delete and DeleteByAddress remove keys from the keyring.
Delete(uid string) error
@ -76,25 +76,27 @@ type Keyring interface {
// another key is already stored under the same name or address.
//
// A passphrase set to the empty string will set the passphrase to the DefaultBIP39Passphrase value.
NewMnemonic(uid string, language Language, hdPath, bip39Passphrase string, algo SignatureAlgo) (Info, string, error)
NewMnemonic(uid string, language Language, hdPath, bip39Passphrase string, algo SignatureAlgo) (*Record, string, error)
// NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it.
// It fails if there is an existing key Info with the same address.
NewAccount(uid, mnemonic, bip39Passphrase, hdPath string, algo SignatureAlgo) (Info, error)
NewAccount(uid, mnemonic, bip39Passphrase, hdPath string, algo SignatureAlgo) (*Record, error)
// SaveLedgerKey retrieves a public key reference from a Ledger device and persists it.
SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, coinType, account, index uint32) (Info, error)
SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, coinType, account, index uint32) (*Record, error)
// SavePubKey stores a public key and returns the persisted Info structure.
SavePubKey(uid string, pubkey types.PubKey, algo hd.PubKeyType) (Info, error)
// SaveOfflineKey stores a public key and returns the persisted Info structure.
SaveOfflineKey(uid string, pubkey types.PubKey) (*Record, error)
// SaveMultisig stores and returns a new multsig (offline) key reference.
SaveMultisig(uid string, pubkey types.PubKey) (Info, error)
SaveMultisig(uid string, pubkey types.PubKey) (*Record, error)
Signer
Importer
Exporter
Migrator
}
// UnsafeKeyring exposes unsafe operations such as unsafe unarmored export in
@ -122,11 +124,9 @@ type Importer interface {
ImportPubKey(uid string, armor string) error
}
// LegacyInfoImporter is implemented by key stores that support import of Info types.
type LegacyInfoImporter interface {
// ImportInfo import a keyring.Info into the current keyring.
// It is used to migrate multisig, ledger, and public key Info structure.
ImportInfo(oldInfo Info) error
// Migrator is implemented by key stores and enables migration of keys from amino to proto
type Migrator interface {
MigrateAll() (bool, error)
}
// Exporter is implemented by key stores that support export of public and private keys.
@ -162,15 +162,15 @@ type Options struct {
// NewInMemory creates a transient keyring useful for testing
// purposes and on-the-fly key generation.
// Keybase options can be applied when generating this new Keybase.
func NewInMemory(opts ...Option) Keyring {
return newKeystore(keyring.NewArrayKeyring(nil), opts...)
func NewInMemory(cdc codec.Codec, opts ...Option) Keyring {
return newKeystore(keyring.NewArrayKeyring(nil), cdc, opts...)
}
// New creates a new instance of a keyring.
// Keyring ptions can be applied when generating the new instance.
// Available backends are "os", "file", "kwallet", "memory", "pass", "test".
func New(
appName, backend, rootDir string, userInput io.Reader, opts ...Option,
appName, backend, rootDir string, userInput io.Reader, cdc codec.Codec, opts ...Option,
) (Keyring, error) {
var (
db keyring.Keyring
@ -179,7 +179,7 @@ func New(
switch backend {
case BackendMemory:
return NewInMemory(opts...), err
return NewInMemory(cdc, opts...), err
case BackendTest:
db, err = keyring.Open(newTestBackendKeyringConfig(appName, rootDir))
case BackendFile:
@ -198,15 +198,16 @@ func New(
return nil, err
}
return newKeystore(db, opts...), nil
return newKeystore(db, cdc, opts...), nil
}
type keystore struct {
db keyring.Keyring
cdc codec.Codec
options Options
}
func newKeystore(kr keyring.Keyring, opts ...Option) keystore {
func newKeystore(kr keyring.Keyring, cdc codec.Codec, opts ...Option) keystore {
// Default options for keybase
options := Options{
SupportedAlgos: SigningAlgoList{hd.Secp256k1},
@ -217,95 +218,84 @@ func newKeystore(kr keyring.Keyring, opts ...Option) keystore {
optionFn(&options)
}
return keystore{kr, options}
return keystore{kr, cdc, options}
}
func (ks keystore) ExportPubKeyArmor(uid string) (string, error) {
bz, err := ks.Key(uid)
k, err := ks.Key(uid)
if err != nil {
return "", err
}
if bz == nil {
return "", fmt.Errorf("no key to export with name: %s", uid)
key, err := k.GetPubKey()
if err != nil {
return "", err
}
return crypto.ArmorPubKeyBytes(legacy.Cdc.MustMarshal(bz.GetPubKey()), string(bz.GetAlgo())), nil
bz, err := ks.cdc.MarshalInterface(key)
if err != nil {
return "", err
}
return crypto.ArmorPubKeyBytes(bz, key.Type()), nil
}
func (ks keystore) ExportPubKeyArmorByAddress(address sdk.Address) (string, error) {
info, err := ks.KeyByAddress(address)
k, err := ks.KeyByAddress(address)
if err != nil {
return "", err
}
return ks.ExportPubKeyArmor(info.GetName())
return ks.ExportPubKeyArmor(k.Name)
}
// ExportPrivKeyArmor exports encrypted privKey
func (ks keystore) ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) {
priv, err := ks.ExportPrivateKeyObject(uid)
if err != nil {
return "", err
}
info, err := ks.Key(uid)
if err != nil {
return "", err
}
return crypto.EncryptArmorPrivKey(priv, encryptPassphrase, string(info.GetAlgo())), nil
return crypto.EncryptArmorPrivKey(priv, encryptPassphrase, priv.Type()), nil
}
// ExportPrivateKeyObject exports an armored private key object.
func (ks keystore) ExportPrivateKeyObject(uid string) (types.PrivKey, error) {
info, err := ks.Key(uid)
k, err := ks.Key(uid)
if err != nil {
return nil, err
}
var priv types.PrivKey
switch linfo := info.(type) {
case localInfo:
if linfo.PrivKeyArmor == "" {
err = fmt.Errorf("private key not available")
return nil, err
}
priv, err = legacy.PrivKeyFromBytes([]byte(linfo.PrivKeyArmor))
if err != nil {
return nil, err
}
case ledgerInfo, offlineInfo, multiInfo:
return nil, errors.New("only works on local private keys")
priv, err := extractPrivKeyFromRecord(k)
if err != nil {
return nil, err
}
return priv, nil
return priv, err
}
func (ks keystore) ExportPrivKeyArmorByAddress(address sdk.Address, encryptPassphrase string) (armor string, err error) {
byAddress, err := ks.KeyByAddress(address)
k, err := ks.KeyByAddress(address)
if err != nil {
return "", err
}
return ks.ExportPrivKeyArmor(byAddress.GetName(), encryptPassphrase)
return ks.ExportPrivKeyArmor(k.Name, encryptPassphrase)
}
func (ks keystore) ImportPrivKey(uid, armor, passphrase string) error {
if k, err := ks.Key(uid); err == nil {
if uid == k.GetName() {
if uid == k.Name {
return fmt.Errorf("cannot overwrite key: %s", uid)
}
}
privKey, algo, err := crypto.UnarmorDecryptPrivKey(armor, passphrase)
privKey, _, err := crypto.UnarmorDecryptPrivKey(armor, passphrase)
if err != nil {
return errors.Wrap(err, "failed to decrypt private key")
}
_, err = ks.writeLocalKey(uid, privKey, hd.PubKeyType(algo))
_, err = ks.writeLocalKey(uid, privKey)
if err != nil {
return err
}
@ -318,17 +308,17 @@ func (ks keystore) ImportPubKey(uid string, armor string) error {
return fmt.Errorf("cannot overwrite key: %s", uid)
}
pubBytes, algo, err := crypto.UnarmorPubKeyBytes(armor)
pubBytes, _, err := crypto.UnarmorPubKeyBytes(armor)
if err != nil {
return err
}
pubKey, err := legacy.PubKeyFromBytes(pubBytes)
if err != nil {
var pubKey types.PubKey
if err := ks.cdc.UnmarshalInterface(pubBytes, &pubKey); err != nil {
return err
}
_, err = ks.writeOfflineKey(uid, pubKey, hd.PubKeyType(algo))
_, err = ks.writeOfflineKey(uid, pubKey)
if err != nil {
return err
}
@ -336,59 +326,51 @@ func (ks keystore) ImportPubKey(uid string, armor string) error {
return nil
}
// ImportInfo implements Importer.MigrateInfo.
func (ks keystore) ImportInfo(oldInfo Info) error {
if _, err := ks.Key(oldInfo.GetName()); err == nil {
return fmt.Errorf("cannot overwrite key: %s", oldInfo.GetName())
}
return ks.writeInfo(oldInfo)
}
func (ks keystore) Sign(uid string, msg []byte) ([]byte, types.PubKey, error) {
info, err := ks.Key(uid)
k, err := ks.Key(uid)
if err != nil {
return nil, nil, err
}
var priv types.PrivKey
switch i := info.(type) {
case localInfo:
if i.PrivKeyArmor == "" {
return nil, nil, fmt.Errorf("private key not available")
}
priv, err = legacy.PrivKeyFromBytes([]byte(i.PrivKeyArmor))
switch {
case k.GetLocal() != nil:
priv, err := extractPrivKeyFromLocal(k.GetLocal())
if err != nil {
return nil, nil, err
}
case ledgerInfo:
return SignWithLedger(info, msg)
sig, err := priv.Sign(msg)
if err != nil {
return nil, nil, err
}
case offlineInfo, multiInfo:
return nil, info.GetPubKey(), errors.New("cannot sign with offline keys")
return sig, priv.PubKey(), nil
case k.GetLedger() != nil:
return SignWithLedger(k, msg)
// multi or offline record
default:
pub, err := k.GetPubKey()
if err != nil {
return nil, nil, err
}
return nil, pub, errors.New("cannot sign with offline keys")
}
sig, err := priv.Sign(msg)
if err != nil {
return nil, nil, err
}
return sig, priv.PubKey(), nil
}
func (ks keystore) SignByAddress(address sdk.Address, msg []byte) ([]byte, types.PubKey, error) {
key, err := ks.KeyByAddress(address)
k, err := ks.KeyByAddress(address)
if err != nil {
return nil, nil, err
}
return ks.Sign(key.GetName(), msg)
return ks.Sign(k.Name, msg)
}
func (ks keystore) SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, coinType, account, index uint32) (Info, error) {
func (ks keystore) SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, coinType, account, index uint32) (*Record, error) {
if !ks.options.SupportedAlgosLedger.Contains(algo) {
return nil, fmt.Errorf(
"%w: signature algo %s is not defined in the keyring options",
@ -403,33 +385,33 @@ func (ks keystore) SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, coi
return nil, fmt.Errorf("failed to generate ledger key: %w", err)
}
return ks.writeLedgerKey(uid, priv.PubKey(), *hdPath, algo.Name())
return ks.writeLedgerKey(uid, priv.PubKey(), hdPath)
}
func (ks keystore) writeLedgerKey(name string, pub types.PubKey, path hd.BIP44Params, algo hd.PubKeyType) (Info, error) {
info := newLedgerInfo(name, pub, path, algo)
if err := ks.writeInfo(info); err != nil {
func (ks keystore) writeLedgerKey(name string, pk types.PubKey, path *hd.BIP44Params) (*Record, error) {
k, err := NewLedgerRecord(name, pk, path)
if err != nil {
return nil, err
}
return info, nil
return k, ks.writeRecord(k)
}
func (ks keystore) SaveMultisig(uid string, pubkey types.PubKey) (Info, error) {
func (ks keystore) SaveMultisig(uid string, pubkey types.PubKey) (*Record, error) {
return ks.writeMultisigKey(uid, pubkey)
}
func (ks keystore) SavePubKey(uid string, pubkey types.PubKey, algo hd.PubKeyType) (Info, error) {
return ks.writeOfflineKey(uid, pubkey, algo)
func (ks keystore) SaveOfflineKey(uid string, pubkey types.PubKey) (*Record, error) {
return ks.writeOfflineKey(uid, pubkey)
}
func (ks keystore) DeleteByAddress(address sdk.Address) error {
info, err := ks.KeyByAddress(address)
k, err := ks.KeyByAddress(address)
if err != nil {
return err
}
err = ks.Delete(info.GetName())
err = ks.Delete(k.Name)
if err != nil {
return err
}
@ -448,13 +430,11 @@ func (ks keystore) Rename(oldName, newName string) error {
return err
}
err = ks.ImportPrivKey(newName, armor, passPhrase)
if err != nil {
if err := ks.Delete(oldName); err != nil {
return err
}
err = ks.Delete(oldName)
if err != nil {
if err := ks.ImportPrivKey(newName, armor, passPhrase); err != nil {
return err
}
@ -462,17 +442,22 @@ func (ks keystore) Rename(oldName, newName string) error {
}
func (ks keystore) Delete(uid string) error {
info, err := ks.Key(uid)
k, err := ks.Key(uid)
if err != nil {
return err
}
err = ks.db.Remove(addrHexKeyAsString(info.GetAddress()))
addr, err := k.GetAddress()
if err != nil {
return err
}
err = ks.db.Remove(infoKey(uid))
err = ks.db.Remove(addrHexKeyAsString(addr))
if err != nil {
return err
}
err = ks.db.Remove(uid)
if err != nil {
return err
}
@ -480,7 +465,7 @@ func (ks keystore) Delete(uid string) error {
return nil
}
func (ks keystore) KeyByAddress(address sdk.Address) (Info, error) {
func (ks keystore) KeyByAddress(address sdk.Address) (*Record, error) {
ik, err := ks.db.Get(addrHexKeyAsString(address))
if err != nil {
return nil, wrapKeyNotFound(err, fmt.Sprint("key with address", address, "not found"))
@ -489,7 +474,8 @@ func (ks keystore) KeyByAddress(address sdk.Address) (Info, error) {
if len(ik.Data) == 0 {
return nil, wrapKeyNotFound(err, fmt.Sprint("key with address", address, "not found"))
}
return ks.key(string(ik.Data))
return ks.Key(string(ik.Data))
}
func wrapKeyNotFound(err error, msg string) error {
@ -499,40 +485,44 @@ func wrapKeyNotFound(err error, msg string) error {
return err
}
func (ks keystore) List() ([]Info, error) {
var res []Info
func (ks keystore) List() ([]*Record, error) {
if _, err := ks.MigrateAll(); err != nil {
return nil, err
}
keys, err := ks.db.Keys()
if err != nil {
return nil, err
}
var res []*Record
sort.Strings(keys)
for _, key := range keys {
if strings.HasSuffix(key, infoSuffix) {
rawInfo, err := ks.db.Get(key)
if err != nil {
return nil, err
}
if len(rawInfo.Data) == 0 {
return nil, sdkerrors.Wrap(sdkerrors.ErrKeyNotFound, key)
}
info, err := unmarshalInfo(rawInfo.Data)
if err != nil {
return nil, err
}
res = append(res, info)
if strings.Contains(key, addressSuffix) {
continue
}
item, err := ks.db.Get(key)
if err != nil {
return nil, err
}
if len(item.Data) == 0 {
return nil, sdkerrors.ErrKeyNotFound.Wrap(key)
}
k, err := ks.protoUnmarshalRecord(item.Data)
if err != nil {
return nil, err
}
res = append(res, k)
}
return res, nil
}
func (ks keystore) NewMnemonic(uid string, language Language, hdPath, bip39Passphrase string, algo SignatureAlgo) (Info, string, error) {
func (ks keystore) NewMnemonic(uid string, language Language, hdPath, bip39Passphrase string, algo SignatureAlgo) (*Record, string, error) {
if language != English {
return nil, "", ErrUnsupportedLanguage
}
@ -557,15 +547,15 @@ func (ks keystore) NewMnemonic(uid string, language Language, hdPath, bip39Passp
bip39Passphrase = DefaultBIP39Passphrase
}
info, err := ks.NewAccount(uid, mnemonic, bip39Passphrase, hdPath, algo)
k, err := ks.NewAccount(uid, mnemonic, bip39Passphrase, hdPath, algo)
if err != nil {
return nil, "", err
}
return info, mnemonic, nil
return k, mnemonic, nil
}
func (ks keystore) NewAccount(name string, mnemonic string, bip39Passphrase string, hdPath string, algo SignatureAlgo) (Info, error) {
func (ks keystore) NewAccount(name string, mnemonic string, bip39Passphrase string, hdPath string, algo SignatureAlgo) (*Record, error) {
if !ks.isSupportedSigningAlgo(algo) {
return nil, ErrUnsupportedSigningAlgo
}
@ -582,29 +572,23 @@ func (ks keystore) NewAccount(name string, mnemonic string, bip39Passphrase stri
// if found
address := sdk.AccAddress(privKey.PubKey().Address())
if _, err := ks.KeyByAddress(address); err == nil {
return nil, fmt.Errorf("account with address %s already exists in keyring, delete the key first if you want to recreate it", address)
return nil, errors.New("duplicated address created")
}
return ks.writeLocalKey(name, privKey, algo.Name())
return ks.writeLocalKey(name, privKey)
}
func (ks keystore) isSupportedSigningAlgo(algo SignatureAlgo) bool {
return ks.options.SupportedAlgos.Contains(algo)
}
func (ks keystore) key(infoKey string) (Info, error) {
bs, err := ks.db.Get(infoKey)
func (ks keystore) Key(uid string) (*Record, error) {
k, _, err := ks.migrate(uid)
if err != nil {
return nil, wrapKeyNotFound(err, infoKey)
return nil, err
}
if len(bs.Data) == 0 {
return nil, sdkerrors.Wrap(sdkerrors.ErrKeyNotFound, infoKey)
}
return unmarshalInfo(bs.Data)
}
func (ks keystore) Key(uid string) (Info, error) {
return ks.key(infoKey(uid))
return k, nil
}
// SupportedAlgorithms returns the keystore Options' supported signing algorithm.
@ -616,17 +600,13 @@ func (ks keystore) SupportedAlgorithms() (SigningAlgoList, SigningAlgoList) {
// SignWithLedger signs a binary message with the ledger device referenced by an Info object
// and returns the signed bytes and the public key. It returns an error if the device could
// not be queried or it returned an error.
func SignWithLedger(info Info, msg []byte) (sig []byte, pub types.PubKey, err error) {
switch info.(type) {
case *ledgerInfo, ledgerInfo:
default:
func SignWithLedger(k *Record, msg []byte) (sig []byte, pub types.PubKey, err error) {
ledgerInfo := k.GetLedger()
if ledgerInfo == nil {
return nil, nil, errors.New("not a ledger object")
}
path, err := info.GetPath()
if err != nil {
return
}
path := ledgerInfo.GetPath()
priv, err := ledger.NewPrivKeySecp256k1Unsafe(*path)
if err != nil {
@ -775,65 +755,70 @@ func newRealPrompt(dir string, buf io.Reader) func(string) (string, error) {
}
}
func (ks keystore) writeLocalKey(name string, priv types.PrivKey, algo hd.PubKeyType) (Info, error) {
// encrypt private key using keyring
pub := priv.PubKey()
info := newLocalInfo(name, pub, string(legacy.Cdc.MustMarshal(priv)), algo)
if err := ks.writeInfo(info); err != nil {
func (ks keystore) writeLocalKey(name string, privKey types.PrivKey) (*Record, error) {
k, err := NewLocalRecord(name, privKey, privKey.PubKey())
if err != nil {
return nil, err
}
return info, nil
return k, ks.writeRecord(k)
}
func (ks keystore) writeInfo(info Info) error {
key := infoKeyBz(info.GetName())
serializedInfo := marshalInfo(info)
// writeRecord persists a keyring item in keystore if it does not exist there
func (ks keystore) writeRecord(k *Record) error {
addr, err := k.GetAddress()
if err != nil {
return err
}
exists, err := ks.existsInDb(info)
key := k.Name
exists, err := ks.existsInDb(addr, key)
if err != nil {
return err
}
if exists {
return errors.New("public key already exists in keybase")
return fmt.Errorf("public key %s already exists in keybase", key)
}
err = ks.db.Set(keyring.Item{
Key: string(key),
Data: serializedInfo,
})
serializedRecord, err := ks.cdc.Marshal(k)
if err != nil {
return fmt.Errorf("unable to serialize record, err - %s", err)
}
item := keyring.Item{
Key: key,
Data: serializedRecord,
}
if err := ks.SetItem(item); err != nil {
return err
}
err = ks.db.Set(keyring.Item{
Key: addrHexKeyAsString(info.GetAddress()),
Data: key,
})
if err != nil {
item = keyring.Item{
Key: addrHexKeyAsString(addr),
Data: []byte(key),
}
if err := ks.SetItem(item); err != nil {
return err
}
return nil
}
// existsInDb returns true if key is in DB. Error is returned only when we have error
// different than ErrKeyNotFound
func (ks keystore) existsInDb(info Info) (bool, error) {
if item, err := ks.db.Get(addrHexKeyAsString(info.GetAddress())); err == nil {
if item.Key == info.GetName() {
return true, nil // address lookup succeeds - info exists
}
return false, nil
// existsInDb returns (true, nil) if either addr or name exist is in keystore DB.
// On the other hand, it returns (false, error) if Get method returns error different from keyring.ErrKeyNotFound
func (ks keystore) existsInDb(addr sdk.Address, name string) (bool, error) {
if _, err := ks.db.Get(addrHexKeyAsString(addr)); err == nil {
return true, nil // address lookup succeeds - info exists
} else if err != keyring.ErrKeyNotFound {
return false, err // received unexpected error - returns error
}
if item, err := ks.db.Get(infoKey(info.GetName())); err == nil {
if item.Key == info.GetName() {
return true, nil // uid lookup succeeds - info exists
}
return false, nil
if _, err := ks.db.Get(name); err == nil {
return true, nil // uid lookup succeeds - info exists
} else if err != keyring.ErrKeyNotFound {
return false, err // received unexpected error - returns
}
@ -842,26 +827,145 @@ func (ks keystore) existsInDb(info Info) (bool, error) {
return false, nil
}
func (ks keystore) writeOfflineKey(name string, pub types.PubKey, algo hd.PubKeyType) (Info, error) {
info := newOfflineInfo(name, pub, algo)
err := ks.writeInfo(info)
func (ks keystore) writeOfflineKey(name string, pk types.PubKey) (*Record, error) {
k, err := NewOfflineRecord(name, pk)
if err != nil {
return nil, err
}
return info, nil
return k, ks.writeRecord(k)
}
func (ks keystore) writeMultisigKey(name string, pub types.PubKey) (Info, error) {
info, err := NewMultiInfo(name, pub)
// writeMultisigKey investigate where thisf function is called maybe remove it
func (ks keystore) writeMultisigKey(name string, pk types.PubKey) (*Record, error) {
k, err := NewMultiRecord(name, pk)
if err != nil {
return nil, err
}
if err = ks.writeInfo(info); err != nil {
return k, ks.writeRecord(k)
}
func (ks keystore) MigrateAll() (bool, error) {
keys, err := ks.db.Keys()
if err != nil {
return false, err
}
if len(keys) == 0 {
return false, nil
}
var migrated bool
for _, key := range keys {
if strings.Contains(key, addressSuffix) {
continue
}
_, migrated2, err := ks.migrate(key)
if err != nil {
fmt.Printf("migrate err: %q", err)
continue
}
if migrated2 {
migrated = true
}
}
return migrated, nil
}
// migrate converts keyring.Item from amino to proto serialization format.
func (ks keystore) migrate(key string) (*Record, bool, error) {
item, err := ks.db.Get(key)
if err != nil {
return nil, false, wrapKeyNotFound(err, key)
}
if len(item.Data) == 0 {
return nil, false, sdkerrors.Wrap(sdkerrors.ErrKeyNotFound, key)
}
// 2.try to deserialize using proto, if good then continue, otherwise try to deserialize using amino
k, err := ks.protoUnmarshalRecord(item.Data)
if err == nil {
return k, false, nil
}
LegacyInfo, err := unMarshalLegacyInfo(item.Data)
if err != nil {
return nil, false, fmt.Errorf("unable to unmarshal item.Data, err: %w", err)
}
// 4.serialize info using proto
k, err = ks.convertFromLegacyInfo(LegacyInfo)
if err != nil {
return nil, false, fmt.Errorf("convertFromLegacyInfo, err: %w", err)
}
serializedRecord, err := ks.cdc.Marshal(k)
if err != nil {
return nil, false, fmt.Errorf("unable to serialize record, err: %w", err)
}
item = keyring.Item{
Key: key,
Data: serializedRecord,
Description: "SDK kerying version",
}
// 5.overwrite the keyring entry with
if err := ks.SetItem(item); err != nil {
return nil, false, fmt.Errorf("unable to set keyring.Item, err: %w", err)
}
return k, true, nil
}
func (ks keystore) protoUnmarshalRecord(bz []byte) (*Record, error) {
k := new(Record)
if err := ks.cdc.Unmarshal(bz, k); err != nil {
return nil, err
}
return info, nil
return k, nil
}
func (ks keystore) SetItem(item keyring.Item) error {
return ks.db.Set(item)
}
func (ks keystore) convertFromLegacyInfo(info LegacyInfo) (*Record, error) {
if info == nil {
return nil, errors.New("unable to convert LegacyInfo to Record cause info is nil")
}
name := info.GetName()
pk := info.GetPubKey()
switch info.GetType() {
case TypeLocal:
priv, err := privKeyFromLegacyInfo(info)
if err != nil {
return nil, err
}
return NewLocalRecord(name, priv, pk)
case TypeOffline:
return NewOfflineRecord(name, pk)
case TypeMulti:
return NewMultiRecord(name, pk)
case TypeLedger:
path, err := info.GetPath()
if err != nil {
return nil, err
}
return NewLedgerRecord(name, pk, path)
default:
return nil, errors.New("unknown LegacyInfo type")
}
}
type unsafeKeystore struct {

View File

@ -1,9 +1,11 @@
//+build ledger test_ledger_mock
//go:build ledger || test_ledger_mock
// +build ledger test_ledger_mock
package keyring
import (
"bytes"
"strings"
"testing"
"github.com/stretchr/testify/require"
@ -13,34 +15,37 @@ import (
)
func TestInMemoryCreateLedger(t *testing.T) {
kb := NewInMemory()
cdc := getCodec()
kb := NewInMemory(cdc)
ledger, err := kb.SaveLedgerKey("some_account", hd.Secp256k1, "cosmos", 118, 3, 1)
k, err := kb.SaveLedgerKey("some_account", hd.Secp256k1, "cosmos", 118, 3, 1)
if err != nil {
require.Error(t, err)
require.Equal(t, "ledger nano S: support for ledger devices is not available in this executable", err.Error())
require.Nil(t, ledger)
require.Nil(t, k)
t.Skip("ledger nano S: support for ledger devices is not available in this executable")
return
}
// The mock is available, check that the address is correct
pubKey := ledger.GetPubKey()
pubKey, err := k.GetPubKey()
require.NoError(t, err)
expectedPkStr := "PubKeySecp256k1{03602C0CB4D8C0081FEE794BDE96E7B95FA16F2B5283B764AC070584327B2C7202}"
require.Equal(t, expectedPkStr, pubKey.String())
// Check that restoring the key gets the same results
restoredKey, err := kb.Key("some_account")
restoredRecord, err := kb.Key("some_account")
require.NoError(t, err)
require.NotNil(t, restoredRecord)
require.Equal(t, "some_account", restoredRecord.Name)
pubKey, err = restoredRecord.GetPubKey()
require.NoError(t, err)
require.NotNil(t, restoredKey)
require.Equal(t, "some_account", restoredKey.GetName())
require.Equal(t, TypeLedger, restoredKey.GetType())
pubKey = restoredKey.GetPubKey()
require.Equal(t, expectedPkStr, pubKey.String())
path, err := restoredKey.GetPath()
require.NoError(t, err)
ledgerInfo := restoredRecord.GetLedger()
require.NotNil(t, ledgerInfo)
path := ledgerInfo.GetPath()
require.Equal(t, "m/44'/118'/3'/0/1", path.String())
}
@ -48,53 +53,58 @@ func TestInMemoryCreateLedger(t *testing.T) {
// signatures
func TestSignVerifyKeyRingWithLedger(t *testing.T) {
dir := t.TempDir()
cdc := getCodec()
kb, err := New("keybasename", "test", dir, nil)
kb, err := New("keybasename", "test", dir, nil, cdc)
require.NoError(t, err)
i1, err := kb.SaveLedgerKey("key", hd.Secp256k1, "cosmos", 118, 0, 0)
k, err := kb.SaveLedgerKey("key", hd.Secp256k1, "cosmos", 118, 0, 0)
if err != nil {
require.Equal(t, "ledger nano S: support for ledger devices is not available in this executable", err.Error())
t.Skip("ledger nano S: support for ledger devices is not available in this executable")
return
}
require.Equal(t, "key", i1.GetName())
require.Equal(t, "key", k.Name)
d1 := []byte("my first message")
s1, pub1, err := kb.Sign("key", d1)
require.NoError(t, err)
s2, pub2, err := SignWithLedger(i1, d1)
s2, pub2, err := SignWithLedger(k, d1)
require.NoError(t, err)
require.True(t, pub1.Equals(pub2))
require.True(t, bytes.Equal(s1, s2))
require.Equal(t, i1.GetPubKey(), pub1)
require.Equal(t, i1.GetPubKey(), pub2)
key1, err := k.GetPubKey()
require.NoError(t, err)
require.Equal(t, key1, pub1)
require.Equal(t, key1, pub2)
require.True(t, pub1.VerifySignature(d1, s1))
require.True(t, i1.GetPubKey().VerifySignature(d1, s1))
require.True(t, key1.VerifySignature(d1, s1))
require.True(t, bytes.Equal(s1, s2))
localInfo, _, err := kb.NewMnemonic("test", English, types.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1)
k, _, err = kb.NewMnemonic("test", English, types.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1)
require.NoError(t, err)
_, _, err = SignWithLedger(localInfo, d1)
_, _, err = SignWithLedger(k, d1)
require.Error(t, err)
require.Equal(t, "not a ledger object", err.Error())
}
func TestAltKeyring_SaveLedgerKey(t *testing.T) {
dir := t.TempDir()
cdc := getCodec()
keyring, err := New(t.Name(), BackendTest, dir, nil)
kr, err := New(t.Name(), BackendTest, dir, nil, cdc)
require.NoError(t, err)
// Test unsupported Algo
_, err = keyring.SaveLedgerKey("key", notSupportedAlgo{}, "cosmos", 118, 0, 0)
_, err = kr.SaveLedgerKey("key", notSupportedAlgo{}, "cosmos", 118, 0, 0)
require.Error(t, err)
require.Contains(t, err.Error(), ErrUnsupportedSigningAlgo.Error())
require.True(t, strings.Contains(err.Error(), ErrUnsupportedSigningAlgo.Error()))
ledger, err := keyring.SaveLedgerKey("some_account", hd.Secp256k1, "cosmos", 118, 3, 1)
k, err := kr.SaveLedgerKey("some_account", hd.Secp256k1, "cosmos", 118, 3, 1)
if err != nil {
require.Equal(t, "ledger nano S: support for ledger devices is not available in this executable", err.Error())
t.Skip("ledger nano S: support for ledger devices is not available in this executable")
@ -102,21 +112,25 @@ func TestAltKeyring_SaveLedgerKey(t *testing.T) {
}
// The mock is available, check that the address is correct
require.Equal(t, "some_account", ledger.GetName())
pubKey := ledger.GetPubKey()
require.Equal(t, "some_account", k.Name)
pubKey, err := k.GetPubKey()
require.NoError(t, err)
expectedPkStr := "PubKeySecp256k1{03602C0CB4D8C0081FEE794BDE96E7B95FA16F2B5283B764AC070584327B2C7202}"
require.Equal(t, expectedPkStr, pubKey.String())
// Check that restoring the key gets the same results
restoredKey, err := keyring.Key("some_account")
restoredRecord, err := kr.Key("some_account")
require.NoError(t, err)
require.NotNil(t, restoredRecord)
require.Equal(t, "some_account", restoredRecord.Name)
// require.Equal(t, TypeLedger, restoredRecord.GetType())
pubKey, err = restoredRecord.GetPubKey()
require.NoError(t, err)
require.NotNil(t, restoredKey)
require.Equal(t, "some_account", restoredKey.GetName())
require.Equal(t, TypeLedger, restoredKey.GetType())
pubKey = restoredKey.GetPubKey()
require.Equal(t, expectedPkStr, pubKey.String())
path, err := restoredKey.GetPath()
require.NoError(t, err)
ledgerInfo := k.GetLedger()
require.NotNil(t, ledgerInfo)
path := ledgerInfo.GetPath()
require.Equal(t, "m/44'/118'/3'/0/1", path.String())
}

File diff suppressed because it is too large Load Diff

View File

@ -1,192 +0,0 @@
package keyring
import (
"fmt"
"strings"
"github.com/pkg/errors"
tmos "github.com/tendermint/tendermint/libs/os"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/crypto"
"github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
// LegacyKeybase is implemented by the legacy keybase implementation.
type LegacyKeybase interface {
List() ([]Info, error)
Export(name string) (armor string, err error)
ExportPrivKey(name, decryptPassphrase, encryptPassphrase string) (armor string, err error)
ExportPubKey(name string) (armor string, err error)
Close() error
}
// NewLegacy creates a new instance of a legacy keybase.
func NewLegacy(name, dir string, opts ...KeybaseOption) (LegacyKeybase, error) {
if err := tmos.EnsureDir(dir, 0700); err != nil {
return nil, fmt.Errorf("failed to create Keybase directory: %s", err)
}
db, err := sdk.NewLevelDB(name, dir)
if err != nil {
return nil, err
}
return newDBKeybase(db), nil
}
var _ LegacyKeybase = dbKeybase{}
// dbKeybase combines encryption and storage implementation to provide a
// full-featured key manager.
//
// Deprecated: dbKeybase will be removed in favor of keyringKeybase.
type dbKeybase struct {
db dbm.DB
}
// newDBKeybase creates a new dbKeybase instance using the provided DB for
// reading and writing keys.
func newDBKeybase(db dbm.DB) dbKeybase {
return dbKeybase{
db: db,
}
}
// List returns the keys from storage in alphabetical order.
func (kb dbKeybase) List() ([]Info, error) {
var res []Info
iter, err := kb.db.Iterator(nil, nil)
if err != nil {
return nil, err
}
defer iter.Close()
for ; iter.Valid(); iter.Next() {
key := string(iter.Key())
// need to include only keys in storage that have an info suffix
if strings.HasSuffix(key, infoSuffix) {
info, err := unmarshalInfo(iter.Value())
if err != nil {
return nil, err
}
res = append(res, info)
}
}
return res, nil
}
// Get returns the public information about one key.
func (kb dbKeybase) Get(name string) (Info, error) {
bs, err := kb.db.Get(infoKeyBz(name))
if err != nil {
return nil, err
}
if len(bs) == 0 {
return nil, sdkerrors.Wrap(sdkerrors.ErrKeyNotFound, name)
}
return unmarshalInfo(bs)
}
// ExportPrivateKeyObject returns a PrivKey object given the key name and
// passphrase. An error is returned if the key does not exist or if the Info for
// the key is invalid.
func (kb dbKeybase) ExportPrivateKeyObject(name string, passphrase string) (types.PrivKey, error) {
info, err := kb.Get(name)
if err != nil {
return nil, err
}
var priv types.PrivKey
switch i := info.(type) {
case localInfo:
linfo := i
if linfo.PrivKeyArmor == "" {
err = fmt.Errorf("private key not available")
return nil, err
}
priv, _, err = crypto.UnarmorDecryptPrivKey(linfo.PrivKeyArmor, passphrase)
if err != nil {
return nil, err
}
case ledgerInfo, offlineInfo, multiInfo:
return nil, errors.New("only works on local private keys")
}
return priv, nil
}
func (kb dbKeybase) Export(name string) (armor string, err error) {
bz, err := kb.db.Get(infoKeyBz(name))
if err != nil {
return "", err
}
if bz == nil {
return "", fmt.Errorf("no key to export with name %s", name)
}
return crypto.ArmorInfoBytes(bz), nil
}
// ExportPubKey returns public keys in ASCII armored format. It retrieves a Info
// object by its name and return the public key in a portable format.
func (kb dbKeybase) ExportPubKey(name string) (armor string, err error) {
bz, err := kb.db.Get(infoKeyBz(name))
if err != nil {
return "", err
}
if bz == nil {
return "", fmt.Errorf("no key to export with name %s", name)
}
info, err := unmarshalInfo(bz)
if err != nil {
return
}
return crypto.ArmorPubKeyBytes(info.GetPubKey().Bytes(), string(info.GetAlgo())), nil
}
// ExportPrivKey returns a private key in ASCII armored format.
// It returns an error if the key does not exist or a wrong encryption passphrase
// is supplied.
func (kb dbKeybase) ExportPrivKey(name string, decryptPassphrase string,
encryptPassphrase string) (armor string, err error) {
priv, err := kb.ExportPrivateKeyObject(name, decryptPassphrase)
if err != nil {
return "", err
}
info, err := kb.Get(name)
if err != nil {
return "", err
}
return crypto.EncryptArmorPrivKey(priv, encryptPassphrase, string(info.GetAlgo())), nil
}
// Close the underlying storage.
func (kb dbKeybase) Close() error { return kb.db.Close() }
func infoKey(name string) string { return fmt.Sprintf("%s.%s", name, infoSuffix) }
func infoKeyBz(name string) []byte { return []byte(infoKey(name)) }
// KeybaseOption overrides options for the db.
type KeybaseOption func(*kbOptions)
type kbOptions struct {
}

View File

@ -8,11 +8,11 @@ import (
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// Info is the publicly exposed information about a keypair
type Info interface {
// Deprecated: LegacyInfo is the publicly exposed information about a keypair
type LegacyInfo interface {
// Human-readable type for key listing
GetType() KeyType
// Name of the key
@ -20,7 +20,7 @@ type Info interface {
// Public key
GetPubKey() cryptotypes.PubKey
// Address
GetAddress() types.AccAddress
GetAddress() sdk.AccAddress
// Bip44 Path
GetPath() (*hd.BIP44Params, error)
// Algo
@ -28,152 +28,131 @@ type Info interface {
}
var (
_ Info = &localInfo{}
_ Info = &ledgerInfo{}
_ Info = &offlineInfo{}
_ Info = &multiInfo{}
_ LegacyInfo = &legacyLocalInfo{}
_ LegacyInfo = &legacyLedgerInfo{}
_ LegacyInfo = &legacyOfflineInfo{}
_ LegacyInfo = &LegacyMultiInfo{}
)
// localInfo is the public information about a locally stored key
// legacyLocalInfo is the public information about a locally stored key
// Note: Algo must be last field in struct for backwards amino compatibility
type localInfo struct {
type legacyLocalInfo struct {
Name string `json:"name"`
PubKey cryptotypes.PubKey `json:"pubkey"`
PrivKeyArmor string `json:"privkey.armor"`
Algo hd.PubKeyType `json:"algo"`
}
func newLocalInfo(name string, pub cryptotypes.PubKey, privArmor string, algo hd.PubKeyType) Info {
return &localInfo{
Name: name,
PubKey: pub,
PrivKeyArmor: privArmor,
Algo: algo,
}
}
// GetType implements Info interface
func (i localInfo) GetType() KeyType {
func (i legacyLocalInfo) GetType() KeyType {
return TypeLocal
}
// GetType implements Info interface
func (i localInfo) GetName() string {
func (i legacyLocalInfo) GetName() string {
return i.Name
}
// GetType implements Info interface
func (i localInfo) GetPubKey() cryptotypes.PubKey {
func (i legacyLocalInfo) GetPubKey() cryptotypes.PubKey {
return i.PubKey
}
// GetType implements Info interface
func (i localInfo) GetAddress() types.AccAddress {
func (i legacyLocalInfo) GetAddress() sdk.AccAddress {
return i.PubKey.Address().Bytes()
}
// GetPrivKeyArmor
func (i legacyLocalInfo) GetPrivKeyArmor() string {
return i.PrivKeyArmor
}
// GetType implements Info interface
func (i localInfo) GetAlgo() hd.PubKeyType {
func (i legacyLocalInfo) GetAlgo() hd.PubKeyType {
return i.Algo
}
// GetType implements Info interface
func (i localInfo) GetPath() (*hd.BIP44Params, error) {
func (i legacyLocalInfo) GetPath() (*hd.BIP44Params, error) {
return nil, fmt.Errorf("BIP44 Paths are not available for this type")
}
// ledgerInfo is the public information about a Ledger key
// legacyLedgerInfo is the public information about a Ledger key
// Note: Algo must be last field in struct for backwards amino compatibility
type ledgerInfo struct {
type legacyLedgerInfo struct {
Name string `json:"name"`
PubKey cryptotypes.PubKey `json:"pubkey"`
Path hd.BIP44Params `json:"path"`
Algo hd.PubKeyType `json:"algo"`
}
func newLedgerInfo(name string, pub cryptotypes.PubKey, path hd.BIP44Params, algo hd.PubKeyType) Info {
return &ledgerInfo{
Name: name,
PubKey: pub,
Path: path,
Algo: algo,
}
}
// GetType implements Info interface
func (i ledgerInfo) GetType() KeyType {
func (i legacyLedgerInfo) GetType() KeyType {
return TypeLedger
}
// GetName implements Info interface
func (i ledgerInfo) GetName() string {
func (i legacyLedgerInfo) GetName() string {
return i.Name
}
// GetPubKey implements Info interface
func (i ledgerInfo) GetPubKey() cryptotypes.PubKey {
func (i legacyLedgerInfo) GetPubKey() cryptotypes.PubKey {
return i.PubKey
}
// GetAddress implements Info interface
func (i ledgerInfo) GetAddress() types.AccAddress {
func (i legacyLedgerInfo) GetAddress() sdk.AccAddress {
return i.PubKey.Address().Bytes()
}
// GetPath implements Info interface
func (i ledgerInfo) GetAlgo() hd.PubKeyType {
func (i legacyLedgerInfo) GetAlgo() hd.PubKeyType {
return i.Algo
}
// GetPath implements Info interface
func (i ledgerInfo) GetPath() (*hd.BIP44Params, error) {
func (i legacyLedgerInfo) GetPath() (*hd.BIP44Params, error) {
tmp := i.Path
return &tmp, nil
}
// offlineInfo is the public information about an offline key
// legacyOfflineInfo is the public information about an offline key
// Note: Algo must be last field in struct for backwards amino compatibility
type offlineInfo struct {
type legacyOfflineInfo struct {
Name string `json:"name"`
PubKey cryptotypes.PubKey `json:"pubkey"`
Algo hd.PubKeyType `json:"algo"`
}
func newOfflineInfo(name string, pub cryptotypes.PubKey, algo hd.PubKeyType) Info {
return &offlineInfo{
Name: name,
PubKey: pub,
Algo: algo,
}
}
// GetType implements Info interface
func (i offlineInfo) GetType() KeyType {
func (i legacyOfflineInfo) GetType() KeyType {
return TypeOffline
}
// GetName implements Info interface
func (i offlineInfo) GetName() string {
func (i legacyOfflineInfo) GetName() string {
return i.Name
}
// GetPubKey implements Info interface
func (i offlineInfo) GetPubKey() cryptotypes.PubKey {
func (i legacyOfflineInfo) GetPubKey() cryptotypes.PubKey {
return i.PubKey
}
// GetAlgo returns the signing algorithm for the key
func (i offlineInfo) GetAlgo() hd.PubKeyType {
func (i legacyOfflineInfo) GetAlgo() hd.PubKeyType {
return i.Algo
}
// GetAddress implements Info interface
func (i offlineInfo) GetAddress() types.AccAddress {
func (i legacyOfflineInfo) GetAddress() sdk.AccAddress {
return i.PubKey.Address().Bytes()
}
// GetPath implements Info interface
func (i offlineInfo) GetPath() (*hd.BIP44Params, error) {
func (i legacyOfflineInfo) GetPath() (*hd.BIP44Params, error) {
return nil, fmt.Errorf("BIP44 Paths are not available for this type")
}
@ -187,68 +166,68 @@ type multisigPubKeyInfo struct {
}
// multiInfo is the public information about a multisig key
type multiInfo struct {
type LegacyMultiInfo struct {
Name string `json:"name"`
PubKey cryptotypes.PubKey `json:"pubkey"`
Threshold uint `json:"threshold"`
PubKeys []multisigPubKeyInfo `json:"pubkeys"`
}
// NewMultiInfo creates a new multiInfo instance
func NewMultiInfo(name string, pub cryptotypes.PubKey) (Info, error) {
// NewLegacyMultiInfo creates a new legacyMultiInfo instance
func NewLegacyMultiInfo(name string, pub cryptotypes.PubKey) (LegacyInfo, error) {
if _, ok := pub.(*multisig.LegacyAminoPubKey); !ok {
return nil, fmt.Errorf("MultiInfo supports only multisig.LegacyAminoPubKey, got %T", pub)
}
return &multiInfo{
return &LegacyMultiInfo{
Name: name,
PubKey: pub,
}, nil
}
// GetType implements Info interface
func (i multiInfo) GetType() KeyType {
func (i LegacyMultiInfo) GetType() KeyType {
return TypeMulti
}
// GetName implements Info interface
func (i multiInfo) GetName() string {
func (i LegacyMultiInfo) GetName() string {
return i.Name
}
// GetPubKey implements Info interface
func (i multiInfo) GetPubKey() cryptotypes.PubKey {
func (i LegacyMultiInfo) GetPubKey() cryptotypes.PubKey {
return i.PubKey
}
// GetAddress implements Info interface
func (i multiInfo) GetAddress() types.AccAddress {
func (i LegacyMultiInfo) GetAddress() sdk.AccAddress {
return i.PubKey.Address().Bytes()
}
// GetPath implements Info interface
func (i multiInfo) GetAlgo() hd.PubKeyType {
func (i LegacyMultiInfo) GetAlgo() hd.PubKeyType {
return hd.MultiType
}
// GetPath implements Info interface
func (i multiInfo) GetPath() (*hd.BIP44Params, error) {
func (i LegacyMultiInfo) GetPath() (*hd.BIP44Params, error) {
return nil, fmt.Errorf("BIP44 Paths are not available for this type")
}
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (i multiInfo) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
func (i LegacyMultiInfo) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
multiPK := i.PubKey.(*multisig.LegacyAminoPubKey)
return codectypes.UnpackInterfaces(multiPK, unpacker)
}
// encoding info
func marshalInfo(i Info) []byte {
func MarshalInfo(i LegacyInfo) []byte {
return legacy.Cdc.MustMarshalLengthPrefixed(i)
}
// decoding info
func unmarshalInfo(bz []byte) (info Info, err error) {
func unMarshalLegacyInfo(bz []byte) (info LegacyInfo, err error) {
err = legacy.Cdc.UnmarshalLengthPrefixed(bz, &info)
if err != nil {
return nil, err
@ -261,9 +240,9 @@ func unmarshalInfo(bz []byte) (info Info, err error) {
//
// This is a workaround, as go cannot check that an interface (Info)
// implements another interface (UnpackInterfacesMessage).
_, ok := info.(multiInfo)
_, ok := info.(LegacyMultiInfo)
if ok {
var multi multiInfo
var multi LegacyMultiInfo
err = legacy.Cdc.UnmarshalLengthPrefixed(bz, &multi)
return multi, err
@ -271,3 +250,23 @@ func unmarshalInfo(bz []byte) (info Info, err error) {
return
}
// privKeyFromLegacyInfo exports a private key from LegacyInfo
func privKeyFromLegacyInfo(info LegacyInfo) (cryptotypes.PrivKey, error) {
switch linfo := info.(type) {
case legacyLocalInfo:
if linfo.PrivKeyArmor == "" {
return nil, fmt.Errorf("private key not available")
}
priv, err := legacy.PrivKeyFromBytes([]byte(linfo.PrivKeyArmor))
if err != nil {
return nil, err
}
return priv, nil
// case legacyLedgerInfo, legacyOfflineInfo, LegacyMultiInfo:
default:
return nil, fmt.Errorf("only works on local private keys, provided %s", linfo)
}
}

View File

@ -1,45 +0,0 @@
package keyring_test
import (
"path/filepath"
"testing"
"github.com/otiai10/copy"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
)
func TestNewLegacyKeyBase(t *testing.T) {
dir := t.TempDir()
kb, err := keyring.NewLegacy("keybasename", dir)
require.NoError(t, err)
require.NoError(t, kb.Close())
}
func TestLegacyKeybase(t *testing.T) {
dir := t.TempDir()
// Backup testdata
require.NoError(t, copy.Copy("testdata", dir))
kb, err := keyring.NewLegacy("keys", filepath.Join(dir, "keys"))
require.NoError(t, err)
t.Cleanup(func() { kb.Close() })
keys, err := kb.List()
require.NoError(t, err)
require.Equal(t, 2, len(keys))
armor, err := kb.ExportPubKey(keys[0].GetName())
require.NoError(t, err)
require.NotEmpty(t, armor)
_, err = kb.ExportPrivKey(keys[0].GetName(), "12345678", "12345678")
require.Error(t, err)
armoredInfo, err := kb.Export(keys[0].GetName())
require.NoError(t, err)
require.NotEmpty(t, armoredInfo)
}

View File

@ -0,0 +1,273 @@
package keyring
import (
"strings"
"testing"
"github.com/99designs/keyring"
"github.com/stretchr/testify/suite"
"github.com/cosmos/cosmos-sdk/codec/legacy"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
const n1 = "cosmos"
type MigrationTestSuite struct {
suite.Suite
kb Keyring
priv cryptotypes.PrivKey
pub cryptotypes.PubKey
ks keystore
}
func (s *MigrationTestSuite) SetupSuite() {
dir := s.T().TempDir()
mockIn := strings.NewReader("")
cdc := getCodec()
kb, err := New(n1, BackendTest, dir, mockIn, cdc)
s.Require().NoError(err)
ks, ok := kb.(keystore)
s.Require().True(ok)
s.kb = kb
s.ks = ks
s.priv = cryptotypes.PrivKey(secp256k1.GenPrivKey())
s.pub = s.priv.PubKey()
}
func (s *MigrationTestSuite) TestMigrateLegacyLocalKey() {
legacyLocalInfo := newLegacyLocalInfo(n1, s.pub, string(legacy.Cdc.MustMarshal(s.priv)), hd.Secp256k1.Name())
serializedLegacyLocalInfo := MarshalInfo(legacyLocalInfo)
item := keyring.Item{
Key: n1,
Data: serializedLegacyLocalInfo,
Description: "SDK kerying version",
}
s.Require().NoError(s.ks.SetItem(item))
_, migrated, err := s.ks.migrate(n1)
s.Require().True(migrated)
s.Require().NoError(err)
}
func (s *MigrationTestSuite) TestMigrateLegacyLedgerKey() {
account, coinType, index := uint32(118), uint32(0), uint32(0)
hdPath := hd.NewFundraiserParams(account, coinType, index)
legacyLedgerInfo := newLegacyLedgerInfo(n1, s.pub, *hdPath, hd.Secp256k1.Name())
serializedLegacyLedgerInfo := MarshalInfo(legacyLedgerInfo)
item := keyring.Item{
Key: n1,
Data: serializedLegacyLedgerInfo,
Description: "SDK kerying version",
}
s.Require().NoError(s.ks.SetItem(item))
_, migrated, err := s.ks.migrate(n1)
s.Require().True(migrated)
s.Require().NoError(err)
}
func (s *MigrationTestSuite) TestMigrateLegacyOfflineKey() {
legacyOfflineInfo := newLegacyOfflineInfo(n1, s.pub, hd.Secp256k1.Name())
serializedLegacyOfflineInfo := MarshalInfo(legacyOfflineInfo)
item := keyring.Item{
Key: n1,
Data: serializedLegacyOfflineInfo,
Description: "SDK kerying version",
}
s.Require().NoError(s.ks.SetItem(item))
_, migrated, err := s.ks.migrate(n1)
s.Require().True(migrated)
s.Require().NoError(err)
}
func (s *MigrationTestSuite) TestMigrateLegacyMultiKey() {
multi := multisig.NewLegacyAminoPubKey(
1, []cryptotypes.PubKey{
s.pub,
},
)
LegacyMultiInfo, err := NewLegacyMultiInfo(n1, multi)
s.Require().NoError(err)
serializedLegacyMultiInfo := MarshalInfo(LegacyMultiInfo)
item := keyring.Item{
Key: n1,
Data: serializedLegacyMultiInfo,
Description: "SDK kerying version",
}
s.Require().NoError(s.ks.SetItem(item))
_, migrated, err := s.ks.migrate(n1)
s.Require().True(migrated)
s.Require().NoError(err)
}
func (s *MigrationTestSuite) TestMigrateLocalRecord() {
k1, err := NewLocalRecord("test record", s.priv, s.pub)
s.Require().NoError(err)
serializedRecord, err := s.ks.cdc.Marshal(k1)
s.Require().NoError(err)
item := keyring.Item{
Key: n1,
Data: serializedRecord,
Description: "SDK kerying version",
}
s.Require().NoError(s.ks.SetItem(item))
k2, migrated, err := s.ks.migrate(n1)
s.Require().Equal(k2.Name, k1.Name)
pub, err := k2.GetPubKey()
s.Require().NoError(err)
s.Require().Equal(pub, s.pub)
priv, err := extractPrivKeyFromRecord(k2)
s.Require().NoError(err)
s.Require().Equal(priv, s.priv)
s.Require().False(migrated)
s.Require().NoError(err)
}
func (s *MigrationTestSuite) TestMigrateOneRandomItemError() {
randomBytes := []byte("abckd0s03l")
errItem := keyring.Item{
Key: n1,
Data: randomBytes,
Description: "SDK kerying version",
}
s.Require().NoError(s.ks.SetItem(errItem))
_, migrated, err := s.ks.migrate(n1)
s.Require().False(migrated)
s.Require().Error(err)
}
func (s *MigrationTestSuite) TestMigrateAllLegacyMultiOffline() {
multi := multisig.NewLegacyAminoPubKey(
1, []cryptotypes.PubKey{
s.pub,
},
)
LegacyMultiInfo, err := NewLegacyMultiInfo(n1, multi)
s.Require().NoError(err)
serializedLegacyMultiInfo := MarshalInfo(LegacyMultiInfo)
item := keyring.Item{
Key: n1,
Data: serializedLegacyMultiInfo,
Description: "SDK kerying version",
}
s.Require().NoError(s.ks.SetItem(item))
legacyOfflineInfo := newLegacyOfflineInfo(n1, s.pub, hd.Secp256k1.Name())
serializedLegacyOfflineInfo := MarshalInfo(legacyOfflineInfo)
item = keyring.Item{
Key: n1,
Data: serializedLegacyOfflineInfo,
Description: "SDK kerying version",
}
s.Require().NoError(s.ks.SetItem(item))
migrated, err := s.kb.MigrateAll()
s.Require().True(migrated)
s.Require().NoError(err)
}
func (s *MigrationTestSuite) TestMigrateAllNoItem() {
migrated, err := s.kb.MigrateAll()
s.Require().False(migrated)
s.Require().NoError(err)
}
func (s *MigrationTestSuite) TestMigrateErrUnknownItemKey() {
legacyOfflineInfo := newLegacyOfflineInfo(n1, s.pub, hd.Secp256k1.Name())
serializedLegacyOfflineInfo := MarshalInfo(legacyOfflineInfo)
item := keyring.Item{
Key: n1,
Data: serializedLegacyOfflineInfo,
Description: "SDK kerying version",
}
s.Require().NoError(s.ks.SetItem(item))
incorrectItemKey := n1 + "1"
_, migrated, err := s.ks.migrate(incorrectItemKey)
s.Require().False(migrated)
s.Require().EqualError(err, sdkerrors.Wrap(sdkerrors.ErrKeyNotFound, incorrectItemKey).Error())
}
func (s *MigrationTestSuite) TestMigrateErrEmptyItemData() {
item := keyring.Item{
Key: n1,
Data: []byte{},
Description: "SDK kerying version",
}
s.Require().NoError(s.ks.SetItem(item))
_, migrated, err := s.ks.migrate(n1)
s.Require().False(migrated)
s.Require().EqualError(err, sdkerrors.Wrap(sdkerrors.ErrKeyNotFound, n1).Error())
}
func TestMigrationTestSuite(t *testing.T) {
suite.Run(t, new(MigrationTestSuite))
}
// newLegacyLocalInfo creates a new legacyLocalInfo instance
func newLegacyLocalInfo(name string, pub cryptotypes.PubKey, privArmor string, algo hd.PubKeyType) LegacyInfo {
return &legacyLocalInfo{
Name: name,
PubKey: pub,
PrivKeyArmor: privArmor,
Algo: algo,
}
}
// newLegacyOfflineInfo creates a new legacyLedgerInfo instance
func newLegacyLedgerInfo(name string, pub cryptotypes.PubKey, path hd.BIP44Params, algo hd.PubKeyType) LegacyInfo {
return &legacyLedgerInfo{
Name: name,
PubKey: pub,
Path: path,
Algo: algo,
}
}
// newLegacyOfflineInfo creates a new legacyOfflineInfo instance
func newLegacyOfflineInfo(name string, pub cryptotypes.PubKey, algo hd.PubKeyType) LegacyInfo {
return &legacyOfflineInfo{
Name: name,
PubKey: pub,
Algo: algo,
}
}

View File

@ -39,36 +39,47 @@ func NewKeyOutput(name string, keyType KeyType, a sdk.Address, pk cryptotypes.Pu
}
// MkConsKeyOutput create a KeyOutput in with "cons" Bech32 prefixes.
func MkConsKeyOutput(keyInfo Info) (KeyOutput, error) {
pk := keyInfo.GetPubKey()
func MkConsKeyOutput(k *Record) (KeyOutput, error) {
pk, err := k.GetPubKey()
if err != nil {
return KeyOutput{}, err
}
addr := sdk.ConsAddress(pk.Address())
return NewKeyOutput(keyInfo.GetName(), keyInfo.GetType(), addr, pk)
return NewKeyOutput(k.Name, k.GetType(), addr, pk)
}
// MkValKeyOutput create a KeyOutput in with "val" Bech32 prefixes.
func MkValKeyOutput(keyInfo Info) (KeyOutput, error) {
pk := keyInfo.GetPubKey()
func MkValKeyOutput(k *Record) (KeyOutput, error) {
pk, err := k.GetPubKey()
if err != nil {
return KeyOutput{}, err
}
addr := sdk.ValAddress(pk.Address())
return NewKeyOutput(keyInfo.GetName(), keyInfo.GetType(), addr, pk)
return NewKeyOutput(k.Name, k.GetType(), addr, pk)
}
// MkAccKeyOutput create a KeyOutput in with "acc" Bech32 prefixes. If the
// public key is a multisig public key, then the threshold and constituent
// public keys will be added.
func MkAccKeyOutput(keyInfo Info) (KeyOutput, error) {
pk := keyInfo.GetPubKey()
func MkAccKeyOutput(k *Record) (KeyOutput, error) {
pk, err := k.GetPubKey()
if err != nil {
return KeyOutput{}, err
}
addr := sdk.AccAddress(pk.Address())
return NewKeyOutput(keyInfo.GetName(), keyInfo.GetType(), addr, pk)
return NewKeyOutput(k.Name, k.GetType(), addr, pk)
}
// MkAccKeysOutput returns a slice of KeyOutput objects, each with the "acc"
// Bech32 prefixes, given a slice of Info objects. It returns an error if any
// Bech32 prefixes, given a slice of Record objects. It returns an error if any
// call to MkKeyOutput fails.
func MkAccKeysOutput(infos []Info) ([]KeyOutput, error) {
kos := make([]KeyOutput, len(infos))
func MkAccKeysOutput(records []*Record) ([]KeyOutput, error) {
kos := make([]KeyOutput, len(records))
var err error
for i, info := range infos {
kos[i], err = MkAccKeyOutput(info)
for i, r := range records {
kos[i], err = MkAccKeyOutput(r)
if err != nil {
return nil, err
}

View File

@ -17,14 +17,17 @@ func TestBech32KeysOutput(t *testing.T) {
tmpKey := sk.PubKey()
multisigPk := kmultisig.NewLegacyAminoPubKey(1, []types.PubKey{tmpKey})
info, err := NewMultiInfo("multisig", multisigPk)
k, err := NewMultiRecord("multisig", multisigPk)
require.NotNil(t, k)
require.NoError(t, err)
accAddr := sdk.AccAddress(info.GetPubKey().Address())
expectedOutput, err := NewKeyOutput(info.GetName(), info.GetType(), accAddr, multisigPk)
pubKey, err := k.GetPubKey()
require.NoError(t, err)
accAddr := sdk.AccAddress(pubKey.Address())
expectedOutput, err := NewKeyOutput(k.Name, k.GetType(), accAddr, multisigPk)
require.NoError(t, err)
out, err := MkAccKeyOutput(info)
out, err := MkAccKeyOutput(k)
require.NoError(t, err)
require.Equal(t, expectedOutput, out)
require.Equal(t, `{Name:multisig Type:multi Address:cosmos1nf8lf6n4wa43rzmdzwe6hkrnw5guekhqt595cw PubKey:{"@type":"/cosmos.crypto.multisig.LegacyAminoPubKey","threshold":1,"public_keys":[{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AurroA7jvfPd1AadmmOvWM2rJSwipXfRf8yD6pLbA2DJ"}]} Mnemonic:}`, fmt.Sprintf("%+v", out))
require.Equal(t, "{Name:multisig Type:multi Address:cosmos1nf8lf6n4wa43rzmdzwe6hkrnw5guekhqt595cw PubKey:{\"@type\":\"/cosmos.crypto.multisig.LegacyAminoPubKey\",\"threshold\":1,\"public_keys\":[{\"@type\":\"/cosmos.crypto.secp256k1.PubKey\",\"key\":\"AurroA7jvfPd1AadmmOvWM2rJSwipXfRf8yD6pLbA2DJ\"}]} Mnemonic:}", fmt.Sprintf("%+v", out))
}

132
crypto/keyring/record.go Normal file
View File

@ -0,0 +1,132 @@
package keyring
import (
"errors"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/hd"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/types"
)
// ErrPrivKeyExtr is used to output an error if extraction of a private key from Local item fails
var ErrPrivKeyExtr = errors.New("private key extraction works only for Local")
func newRecord(name string, pk cryptotypes.PubKey, item isRecord_Item) (*Record, error) {
any, err := codectypes.NewAnyWithValue(pk)
if err != nil {
return nil, err
}
return &Record{name, any, item}, nil
}
// NewLocalRecord creates a new Record with local key item
func NewLocalRecord(name string, priv cryptotypes.PrivKey, pk cryptotypes.PubKey) (*Record, error) {
any, err := codectypes.NewAnyWithValue(priv)
if err != nil {
return nil, err
}
recordLocal := &Record_Local{any, priv.Type()}
recordLocalItem := &Record_Local_{recordLocal}
return newRecord(name, pk, recordLocalItem)
}
// NewLedgerRecord creates a new Record with ledger item
func NewLedgerRecord(name string, pk cryptotypes.PubKey, path *hd.BIP44Params) (*Record, error) {
recordLedger := &Record_Ledger{path}
recordLedgerItem := &Record_Ledger_{recordLedger}
return newRecord(name, pk, recordLedgerItem)
}
func (rl *Record_Ledger) GetPath() *hd.BIP44Params {
return rl.Path
}
// NewOfflineRecord creates a new Record with offline item
func NewOfflineRecord(name string, pk cryptotypes.PubKey) (*Record, error) {
recordOffline := &Record_Offline{}
recordOfflineItem := &Record_Offline_{recordOffline}
return newRecord(name, pk, recordOfflineItem)
}
// NewMultiRecord creates a new Record with multi item
func NewMultiRecord(name string, pk cryptotypes.PubKey) (*Record, error) {
recordMulti := &Record_Multi{}
recordMultiItem := &Record_Multi_{recordMulti}
return newRecord(name, pk, recordMultiItem)
}
// GetPubKey fetches a public key of the record
func (k *Record) GetPubKey() (cryptotypes.PubKey, error) {
pk, ok := k.PubKey.GetCachedValue().(cryptotypes.PubKey)
if !ok {
return nil, errors.New("unable to cast any to cryptotypes.PubKey")
}
return pk, nil
}
// GetAddress fetches an address of the record
func (k Record) GetAddress() (types.AccAddress, error) {
pk, err := k.GetPubKey()
if err != nil {
return nil, err
}
return pk.Address().Bytes(), nil
}
// GetType fetches type of the record
func (k Record) GetType() KeyType {
switch {
case k.GetLocal() != nil:
return TypeLocal
case k.GetLedger() != nil:
return TypeLedger
case k.GetMulti() != nil:
return TypeMulti
case k.GetOffline() != nil:
return TypeOffline
default:
panic("unrecognized record type")
}
}
// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces
func (k *Record) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
var pk cryptotypes.PubKey
if err := unpacker.UnpackAny(k.PubKey, &pk); err != nil {
return err
}
if l := k.GetLocal(); l != nil {
var priv cryptotypes.PrivKey
return unpacker.UnpackAny(l.PrivKey, &priv)
}
return nil
}
func extractPrivKeyFromRecord(k *Record) (cryptotypes.PrivKey, error) {
rl := k.GetLocal()
if rl == nil {
return nil, ErrPrivKeyExtr
}
return extractPrivKeyFromLocal(rl)
}
func extractPrivKeyFromLocal(rl *Record_Local) (cryptotypes.PrivKey, error) {
if rl.PrivKey == nil {
return nil, errors.New("private key is not available")
}
priv, ok := rl.PrivKey.GetCachedValue().(cryptotypes.PrivKey)
if !ok {
return nil, errors.New("unable to cast any to cryptotypes.PrivKey")
}
return priv, nil
}

1377
crypto/keyring/record.pb.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,139 @@
package keyring
import (
"strings"
"testing"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/stretchr/testify/suite"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
)
type RecordTestSuite struct {
suite.Suite
appName string
cdc codec.Codec
priv cryptotypes.PrivKey
pub cryptotypes.PubKey
}
func (s *RecordTestSuite) SetupSuite() {
s.appName = "cosmos"
s.cdc = getCodec()
s.priv = cryptotypes.PrivKey(ed25519.GenPrivKey())
s.pub = s.priv.PubKey()
}
func (s *RecordTestSuite) TestOfflineRecordMarshaling() {
k, err := NewOfflineRecord("testrecord", s.pub)
s.Require().NoError(err)
bz, err := s.cdc.Marshal(k)
s.Require().NoError(err)
var k2 Record
s.Require().NoError(s.cdc.Unmarshal(bz, &k2))
s.Require().Equal(k.Name, k2.Name)
s.Require().True(k.PubKey.Equal(k2.PubKey))
pk2, err := k2.GetPubKey()
s.Require().NoError(err)
s.Require().True(s.pub.Equals(pk2))
}
func (s *RecordTestSuite) TestLocalRecordMarshaling() {
dir := s.T().TempDir()
mockIn := strings.NewReader("")
kb, err := New(s.appName, BackendTest, dir, mockIn, s.cdc)
s.Require().NoError(err)
k, err := NewLocalRecord("testrecord", s.priv, s.pub)
s.Require().NoError(err)
ks, ok := kb.(keystore)
s.Require().True(ok)
bz, err := ks.cdc.Marshal(k)
s.Require().NoError(err)
k2, err := ks.protoUnmarshalRecord(bz)
s.Require().NoError(err)
s.Require().Equal(k.Name, k2.Name)
// not sure if this will work -- we can remove this line, the later check is better.
s.Require().True(k.PubKey.Equal(k2.PubKey))
pub2, err := k2.GetPubKey()
s.Require().NoError(err)
s.Require().True(s.pub.Equals(pub2))
localRecord2 := k2.GetLocal()
s.Require().NotNil(localRecord2)
anyPrivKey, err := codectypes.NewAnyWithValue(s.priv)
s.Require().NoError(err)
s.Require().Equal(localRecord2.PrivKey, anyPrivKey)
s.Require().Equal(localRecord2.PrivKeyType, s.priv.Type())
}
func (s *RecordTestSuite) TestLedgerRecordMarshaling() {
dir := s.T().TempDir()
mockIn := strings.NewReader("")
kb, err := New(s.appName, BackendTest, dir, mockIn, s.cdc)
s.Require().NoError(err)
path := hd.NewFundraiserParams(4, 12345, 57)
k, err := NewLedgerRecord("testrecord", s.pub, path)
s.Require().NoError(err)
ks, ok := kb.(keystore)
s.Require().True(ok)
bz, err := ks.cdc.Marshal(k)
s.Require().NoError(err)
k2, err := ks.protoUnmarshalRecord(bz)
s.Require().NoError(err)
s.Require().Equal(k.Name, k2.Name)
// not sure if this will work -- we can remove this line, the later check is better.
s.Require().True(k.PubKey.Equal(k2.PubKey))
pub2, err := k2.GetPubKey()
s.Require().NoError(err)
s.Require().True(s.pub.Equals(pub2))
ledgerRecord2 := k2.GetLedger()
s.Require().NotNil(ledgerRecord2)
s.Require().Nil(k2.GetLocal())
s.Require().Equal(ledgerRecord2.Path.String(), path.String())
}
func (s *RecordTestSuite) TestExtractPrivKeyFromLocalRecord() {
// use proto serialize
k, err := NewLocalRecord("testrecord", s.priv, s.pub)
s.Require().NoError(err)
privKey2, err := extractPrivKeyFromRecord(k)
s.Require().NoError(err)
s.Require().True(privKey2.Equals(s.priv))
}
func (s *RecordTestSuite) TestExtractPrivKeyFromOfflineRecord() {
k, err := NewOfflineRecord("testrecord", s.pub)
s.Require().NoError(err)
privKey2, err := extractPrivKeyFromRecord(k)
s.Require().Error(err)
s.Require().Nil(privKey2)
}
func TestRecordTestSuite(t *testing.T) {
suite.Run(t, new(RecordTestSuite))
}

View File

@ -37,7 +37,6 @@ const (
// bits of entropy to draw when creating a mnemonic
defaultEntropySize = 256
addressSuffix = "address"
infoSuffix = "info"
)
// KeyType reflects a human-readable type for key listing.

View File

@ -19,28 +19,41 @@ func Test_writeReadLedgerInfo(t *testing.T) {
require.NoError(t, err)
copy(tmpKey[:], bz)
lInfo := newLedgerInfo("some_name", &secp256k1.PubKey{Key: tmpKey}, *hd.NewFundraiserParams(5, sdk.CoinType, 1), hd.Secp256k1Type)
require.Equal(t, TypeLedger, lInfo.GetType())
path, err := lInfo.GetPath()
pk := &secp256k1.PubKey{Key: tmpKey}
path := hd.NewFundraiserParams(5, sdk.CoinType, 1)
k, err := NewLedgerRecord("some_name", pk, path)
require.NoError(t, err)
l := k.GetLedger()
require.NotNil(t, l)
path = l.Path
require.Equal(t, "m/44'/118'/5'/0/1", path.String())
pubKey, err := k.GetPubKey()
require.NoError(t, err)
require.Equal(t,
fmt.Sprintf("PubKeySecp256k1{%s}", hexPK),
lInfo.GetPubKey().String())
pubKey.String())
// Serialize and restore
serialized := marshalInfo(lInfo)
restoredInfo, err := unmarshalInfo(serialized)
cdc := getCodec()
serialized, err := cdc.Marshal(k)
require.NoError(t, err)
require.NotNil(t, restoredInfo)
var restoredRecord Record
err = cdc.Unmarshal(serialized, &restoredRecord)
require.NoError(t, err)
require.NotNil(t, restoredRecord)
// Check both keys match
require.Equal(t, lInfo.GetName(), restoredInfo.GetName())
require.Equal(t, lInfo.GetType(), restoredInfo.GetType())
require.Equal(t, lInfo.GetPubKey(), restoredInfo.GetPubKey())
require.Equal(t, k.Name, restoredRecord.Name)
require.Equal(t, k.GetType(), restoredRecord.GetType())
restoredPath, err := restoredInfo.GetPath()
restoredPubKey, err := restoredRecord.GetPubKey()
require.NoError(t, err)
require.Equal(t, pubKey, restoredPubKey)
l = restoredRecord.GetLedger()
require.NotNil(t, l)
restoredPath := l.GetPath()
require.NoError(t, err)
require.Equal(t, path, restoredPath)
}

View File

@ -456,10 +456,9 @@ func TestProtoMarshalJSON(t *testing.T) {
require.True(pk2.Equals(msig))
// Test that we can correctly unmarshal key from keyring output
info, err := keyring.NewMultiInfo("my multisig", msig)
k, err := keyring.NewMultiRecord("my multisig", msig)
require.NoError(err)
ko, err := keyring.MkAccKeyOutput(info)
ko, err := keyring.MkAccKeyOutput(k)
require.NoError(err)
require.Equal(ko.Address, sdk.AccAddress(pk2.Address()).String())
require.Equal(ko.PubKey, string(bz))

View File

@ -8,11 +8,10 @@ import (
"github.com/btcsuite/btcd/btcec"
"github.com/pkg/errors"
"github.com/cosmos/go-bip39"
secp256k1 "github.com/tendermint/btcd/btcec"
"github.com/tendermint/tendermint/crypto"
"github.com/cosmos/go-bip39"
"github.com/cosmos/cosmos-sdk/crypto/hd"
csecp256k1 "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/testutil"

View File

@ -140,7 +140,7 @@ func TestPublicKeyHDPath(t *testing.T) {
// Check with device
for i := 0; i < len(expectedAddrs); i++ {
path := *hd.NewFundraiserParams(0, sdk.CoinType, uint32(i))
t.Logf("Checking keys at %s\n", path)
t.Logf("Checking keys at %s\n", path.String())
priv, addr, err := NewPrivKeySecp256k1(path, "cosmos")
require.NoError(t, err)

View File

@ -225,6 +225,16 @@
- [PrivKey](#cosmos.crypto.ed25519.PrivKey)
- [PubKey](#cosmos.crypto.ed25519.PubKey)
- [cosmos/crypto/hd/v1/hd.proto](#cosmos/crypto/hd/v1/hd.proto)
- [BIP44Params](#cosmos.crypto.hd.v1.BIP44Params)
- [cosmos/crypto/keyring/v1/record.proto](#cosmos/crypto/keyring/v1/record.proto)
- [Record](#cosmos.crypto.keyring.v1.Record)
- [Record.Ledger](#cosmos.crypto.keyring.v1.Record.Ledger)
- [Record.Local](#cosmos.crypto.keyring.v1.Record.Local)
- [Record.Multi](#cosmos.crypto.keyring.v1.Record.Multi)
- [Record.Offline](#cosmos.crypto.keyring.v1.Record.Offline)
- [cosmos/crypto/multisig/keys.proto](#cosmos/crypto/multisig/keys.proto)
- [LegacyAminoPubKey](#cosmos.crypto.multisig.LegacyAminoPubKey)
@ -3579,6 +3589,129 @@ then you must create a new proto message and follow ADR-28 for Address construct
<!-- end messages -->
<!-- end enums -->
<!-- end HasExtensions -->
<!-- end services -->
<a name="cosmos/crypto/hd/v1/hd.proto"></a>
<p align="right"><a href="#top">Top</a></p>
## cosmos/crypto/hd/v1/hd.proto
<a name="cosmos.crypto.hd.v1.BIP44Params"></a>
### BIP44Params
BIP44Params is used as path field in ledger item in Record.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `purpose` | [uint32](#uint32) | | purpose is a constant set to 44' (or 0x8000002C) following the BIP43 recommendation |
| `coin_type` | [uint32](#uint32) | | coin_type is a constant that improves privacy |
| `account` | [uint32](#uint32) | | account splits the key space into independent user identities |
| `change` | [bool](#bool) | | change is a constant used for public derivation. Constant 0 is used for external chain and constant 1 for internal chain. |
| `address_index` | [uint32](#uint32) | | address_index is used as child index in BIP32 derivation |
<!-- end messages -->
<!-- end enums -->
<!-- end HasExtensions -->
<!-- end services -->
<a name="cosmos/crypto/keyring/v1/record.proto"></a>
<p align="right"><a href="#top">Top</a></p>
## cosmos/crypto/keyring/v1/record.proto
<a name="cosmos.crypto.keyring.v1.Record"></a>
### Record
Record is used for representing a key in the keyring.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `name` | [string](#string) | | name represents a name of Record |
| `pub_key` | [google.protobuf.Any](#google.protobuf.Any) | | pub_key represents a public key in any format |
| `local` | [Record.Local](#cosmos.crypto.keyring.v1.Record.Local) | | local stores the public information about a locally stored key |
| `ledger` | [Record.Ledger](#cosmos.crypto.keyring.v1.Record.Ledger) | | ledger stores the public information about a Ledger key |
| `multi` | [Record.Multi](#cosmos.crypto.keyring.v1.Record.Multi) | | Multi does not store any information. |
| `offline` | [Record.Offline](#cosmos.crypto.keyring.v1.Record.Offline) | | Offline does not store any information. |
<a name="cosmos.crypto.keyring.v1.Record.Ledger"></a>
### Record.Ledger
Ledger item
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `path` | [cosmos.crypto.hd.v1.BIP44Params](#cosmos.crypto.hd.v1.BIP44Params) | | |
<a name="cosmos.crypto.keyring.v1.Record.Local"></a>
### Record.Local
Item is a keyring item stored in a keyring backend.
Local item
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `priv_key` | [google.protobuf.Any](#google.protobuf.Any) | | |
| `priv_key_type` | [string](#string) | | |
<a name="cosmos.crypto.keyring.v1.Record.Multi"></a>
### Record.Multi
Multi item
<a name="cosmos.crypto.keyring.v1.Record.Offline"></a>
### Record.Offline
Offline item
<!-- end messages -->
<!-- end enums -->

2
go.sum
View File

@ -578,12 +578,10 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/otiai10/copy v1.6.0 h1:IinKAryFFuPONZ7cm6T6E2QX/vcJwSnlaA5lfoaXIiQ=
github.com/otiai10/copy v1.6.0/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
github.com/otiai10/mint v1.3.2 h1:VYWnrP5fXmz1MXvjuUvcBrXSjGE6xjON+axB/UrpO3E=
github.com/otiai10/mint v1.3.2/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=

View File

@ -0,0 +1,22 @@
syntax = "proto3";
package cosmos.crypto.hd.v1;
import "gogoproto/gogo.proto";
option go_package = "github.com/cosmos/cosmos-sdk/crypto/hd";
option (gogoproto.goproto_getters_all) = false;
// BIP44Params is used as path field in ledger item in Record.
message BIP44Params {
option (gogoproto.goproto_stringer) = false;
// purpose is a constant set to 44' (or 0x8000002C) following the BIP43 recommendation
uint32 purpose = 1;
// coin_type is a constant that improves privacy
uint32 coin_type = 2;
// account splits the key space into independent user identities
uint32 account = 3;
// change is a constant used for public derivation. Constant 0 is used for external chain and constant 1 for internal chain.
bool change = 4;
// address_index is used as child index in BIP32 derivation
uint32 address_index = 5;
}

View File

@ -0,0 +1,47 @@
syntax = "proto3";
package cosmos.crypto.keyring.v1;
import "gogoproto/gogo.proto";
import "google/protobuf/any.proto";
import "cosmos/crypto/hd/v1/hd.proto";
option go_package = "github.com/cosmos/cosmos-sdk/crypto/keyring";
option (gogoproto.goproto_getters_all) = false;
// Record is used for representing a key in the keyring.
message Record {
// name represents a name of Record
string name = 1;
// pub_key represents a public key in any format
google.protobuf.Any pub_key = 2;
// Record contains one of the following items
oneof item {
// local stores the public information about a locally stored key
Local local = 3;
// ledger stores the public information about a Ledger key
Ledger ledger = 4;
// Multi does not store any information.
Multi multi = 5;
// Offline does not store any information.
Offline offline = 6;
}
// Item is a keyring item stored in a keyring backend.
// Local item
message Local {
google.protobuf.Any priv_key = 1;
string priv_key_type = 2;
}
// Ledger item
message Ledger {
hd.v1.BIP44Params path = 1;
}
// Multi item
message Multi {}
// Offline item
message Offline {}
}

View File

@ -5,18 +5,23 @@ import (
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// GenerateCoinKey returns the address of a public key, along with the secret
// phrase to recover the private key.
func GenerateCoinKey(algo keyring.SignatureAlgo) (sdk.AccAddress, string, error) {
func GenerateCoinKey(algo keyring.SignatureAlgo, cdc codec.Codec) (sdk.AccAddress, string, error) {
// generate a private key, with recovery phrase
info, secret, err := keyring.NewInMemory().NewMnemonic("name", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, algo)
k, secret, err := keyring.NewInMemory(cdc).NewMnemonic("name", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, algo)
if err != nil {
return sdk.AccAddress([]byte{}), "", err
}
return sdk.AccAddress(info.GetPubKey().Address()), secret, nil
addr, err := k.GetAddress()
if err != nil {
return nil, "", err
}
return addr, secret, nil
}
// GenerateSaveCoinKey returns the address of a public key, along with the secret
@ -43,10 +48,15 @@ func GenerateSaveCoinKey(keybase keyring.Keyring, keyName string, overwrite bool
}
}
info, secret, err := keybase.NewMnemonic(keyName, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, algo)
k, secret, err := keybase.NewMnemonic(keyName, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, algo)
if err != nil {
return sdk.AccAddress([]byte{}), "", err
}
return sdk.AccAddress(info.GetPubKey().Address()), secret, nil
addr, err := k.GetAddress()
if err != nil {
return nil, "", err
}
return addr, secret, nil
}

View File

@ -8,44 +8,54 @@ import (
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/types"
)
func TestGenerateCoinKey(t *testing.T) {
t.Parallel()
addr, mnemonic, err := server.GenerateCoinKey(hd.Secp256k1)
cdc := simapp.MakeTestEncodingConfig().Codec
addr, mnemonic, err := server.GenerateCoinKey(hd.Secp256k1, cdc)
require.NoError(t, err)
// Test creation
info, err := keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), hd.Secp256k1)
k, err := keyring.NewInMemory(cdc).NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), hd.Secp256k1)
require.NoError(t, err)
require.Equal(t, addr, info.GetAddress())
addr1, err := k.GetAddress()
require.NoError(t, err)
require.Equal(t, addr, addr1)
}
func TestGenerateSaveCoinKey(t *testing.T) {
t.Parallel()
kb, err := keyring.New(t.Name(), "test", t.TempDir(), nil)
encCfg := simapp.MakeTestEncodingConfig()
kb, err := keyring.New(t.Name(), "test", t.TempDir(), nil, encCfg.Codec)
require.NoError(t, err)
addr, mnemonic, err := server.GenerateSaveCoinKey(kb, "keyname", false, hd.Secp256k1)
require.NoError(t, err)
// Test key was actually saved
info, err := kb.Key("keyname")
k, err := kb.Key("keyname")
require.NoError(t, err)
require.Equal(t, addr, info.GetAddress())
addr1, err := k.GetAddress()
require.NoError(t, err)
require.Equal(t, addr, addr1)
// Test in-memory recovery
info, err = keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), hd.Secp256k1)
k, err = keyring.NewInMemory(encCfg.Codec).NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), hd.Secp256k1)
require.NoError(t, err)
require.Equal(t, addr, info.GetAddress())
addr1, err = k.GetAddress()
require.NoError(t, err)
require.Equal(t, addr, addr1)
}
func TestGenerateSaveCoinKeyOverwriteFlag(t *testing.T) {
t.Parallel()
kb, err := keyring.New(t.Name(), "test", t.TempDir(), nil)
encCfg := simapp.MakeTestEncodingConfig()
kb, err := keyring.New(t.Name(), "test", t.TempDir(), nil, encCfg.Codec)
require.NoError(t, err)
keyname := "justakey"

View File

@ -1,8 +1,9 @@
package errors
import (
"github.com/stretchr/testify/assert"
"testing"
"github.com/stretchr/testify/assert"
)
func TestRegisterError(t *testing.T) {

View File

@ -50,9 +50,10 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa
if err != nil {
inBuf := bufio.NewReader(cmd.InOrStdin())
keyringBackend, _ := cmd.Flags().GetString(flags.FlagKeyringBackend)
if keyringBackend != "" && clientCtx.Keyring == nil {
var err error
kr, err = keyring.New(sdk.KeyringServiceName(), keyringBackend, clientCtx.HomeDir, inBuf)
kr, err = keyring.New(sdk.KeyringServiceName(), keyringBackend, clientCtx.HomeDir, inBuf, clientCtx.Codec)
if err != nil {
return err
}
@ -60,11 +61,15 @@ contain valid denominations. Accounts may optionally be supplied with vesting pa
kr = clientCtx.Keyring
}
info, err := kr.Key(args[0])
k, err := kr.Key(args[0])
if err != nil {
return fmt.Errorf("failed to get address from Keyring: %w", err)
}
addr = info.GetAddress()
addr, err = k.GetAddress()
if err != nil {
return err
}
}
coins, err := sdk.ParseCoinsNormalized(args[1])

View File

@ -81,7 +81,7 @@ func TestAddGenesisAccountCmd(t *testing.T) {
if tc.withKeyring {
path := hd.CreateHDPath(118, 0, 0).String()
kr, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, home, nil)
kr, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, home, nil, appCodec)
require.NoError(t, err)
_, _, err = kr.NewMnemonic(tc.addr, keyring.English, path, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
require.NoError(t, err)

View File

@ -6,7 +6,6 @@ import (
"os"
"path/filepath"
serverconfig "github.com/cosmos/cosmos-sdk/server/config"
"github.com/spf13/cast"
"github.com/spf13/cobra"
tmcli "github.com/tendermint/tendermint/libs/cli"
@ -21,6 +20,7 @@ import (
"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/client/rpc"
"github.com/cosmos/cosmos-sdk/server"
serverconfig "github.com/cosmos/cosmos-sdk/server/config"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/simapp/params"

View File

@ -253,7 +253,7 @@ func initTestnetFiles(
memo := fmt.Sprintf("%s@%s:26656", nodeIDs[i], ip)
genFiles = append(genFiles, nodeConfig.GenesisFile())
kb, err := keyring.New(sdk.KeyringServiceName(), args.keyringBackend, nodeDir, inBuf)
kb, err := keyring.New(sdk.KeyringServiceName(), args.keyringBackend, nodeDir, inBuf, clientCtx.Codec)
if err != nil {
return err
}

View File

@ -5,6 +5,10 @@ import (
"fmt"
"testing"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/libs/log"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/server"
@ -12,9 +16,6 @@ import (
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
genutiltest "github.com/cosmos/cosmos-sdk/x/genutil/client/testutil"
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/libs/log"
)
func Test_TestnetCmd(t *testing.T) {

View File

@ -4,8 +4,9 @@ import (
"fmt"
"testing"
"github.com/cosmos/cosmos-sdk/store/types"
"github.com/stretchr/testify/require"
"github.com/cosmos/cosmos-sdk/store/types"
)
func TestStoreGetKVStore(t *testing.T) {

View File

@ -6,7 +6,7 @@ import (
"fmt"
"time"
metrics "github.com/armon/go-metrics"
"github.com/armon/go-metrics"
metricsprom "github.com/armon/go-metrics/prometheus"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/expfmt"

View File

@ -6,7 +6,7 @@ import (
"testing"
"time"
metrics "github.com/armon/go-metrics"
"github.com/armon/go-metrics"
"github.com/prometheus/common/expfmt"
"github.com/stretchr/testify/require"
)

View File

@ -3,7 +3,7 @@ package telemetry
import (
"time"
metrics "github.com/armon/go-metrics"
"github.com/armon/go-metrics"
)
// Common metric key constants

View File

@ -338,7 +338,7 @@ func New(l Logger, baseDir string, cfg Config) (*Network, error) {
nodeIDs[i] = nodeID
valPubKeys[i] = pubKey
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, cfg.KeyringOptions...)
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, cfg.Codec, cfg.KeyringOptions...)
if err != nil {
return nil, err
}

View File

@ -36,7 +36,7 @@ func (s *handlerTestSuite) TestChainAnteDecorators() {
mockAnteDecorator2 := mocks.NewMockAnteDecorator(mockCtrl)
// NOTE: we can't check that mockAnteDecorator2 is passed as the last argument because
// ChainAnteDecorators wraps the decorators into closures, so each decorator is
// receving a closure.
// receiving a closure.
mockAnteDecorator1.EXPECT().AnteHandle(gomock.Eq(ctx), gomock.Eq(tx), true, gomock.Any()).Times(1)
mockAnteDecorator2.EXPECT().AnteHandle(gomock.Eq(ctx), gomock.Eq(tx), true, gomock.Any()).Times(1)

View File

@ -5,9 +5,7 @@ import (
"errors"
"testing"
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/gorilla/mux"
"github.com/golang/mock/gomock"
"github.com/spf13/cobra"
"github.com/stretchr/testify/require"
@ -15,6 +13,7 @@ import (
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/tests/mocks"

View File

@ -92,15 +92,24 @@ func makeMultiSignCmd() func(cmd *cobra.Command, args []string) (err error) {
return err
}
multisigInfo, err := getMultisigInfo(clientCtx, args[1])
k, err := getMultisigRecord(clientCtx, args[1])
if err != nil {
return err
}
pubKey, err := k.GetPubKey()
if err != nil {
return err
}
multisigPub := multisigInfo.GetPubKey().(*kmultisig.LegacyAminoPubKey)
addr, err := k.GetAddress()
if err != nil {
return err
}
multisigPub := pubKey.(*kmultisig.LegacyAminoPubKey)
multisigSig := multisig.NewMultisig(len(multisigPub.PubKeys))
if !clientCtx.Offline {
accnum, seq, err := clientCtx.AccountRetriever.GetAccountNumberSequence(clientCtx, multisigInfo.GetAddress())
accnum, seq, err := clientCtx.AccountRetriever.GetAccountNumberSequence(clientCtx, addr)
if err != nil {
return err
}
@ -264,7 +273,7 @@ func makeBatchMultisignCmd() func(cmd *cobra.Command, args []string) error {
}
scanner := authclient.NewBatchScanner(txCfg, infile)
multisigInfo, err := getMultisigInfo(clientCtx, args[1])
k, err := getMultisigRecord(clientCtx, args[1])
if err != nil {
return err
}
@ -279,8 +288,13 @@ func makeBatchMultisignCmd() func(cmd *cobra.Command, args []string) error {
signatureBatch = append(signatureBatch, sigs)
}
addr, err := k.GetAddress()
if err != nil {
return err
}
if !clientCtx.Offline {
accnum, seq, err := clientCtx.AccountRetriever.GetAccountNumberSequence(clientCtx, multisigInfo.GetAddress())
accnum, seq, err := clientCtx.AccountRetriever.GetAccountNumberSequence(clientCtx, addr)
if err != nil {
return err
}
@ -302,8 +316,11 @@ func makeBatchMultisignCmd() func(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
multisigPub := multisigInfo.GetPubKey().(*kmultisig.LegacyAminoPubKey)
pubKey, err := k.GetPubKey()
if err != nil {
return err
}
multisigPub := pubKey.(*kmultisig.LegacyAminoPubKey)
multisigSig := multisig.NewMultisig(len(multisigPub.PubKeys))
signingData := signing.SignerData{
ChainID: txFactory.ChainID(),
@ -402,15 +419,12 @@ func readSignaturesFromFile(ctx client.Context, filename string) (sigs []signing
return sigs, nil
}
func getMultisigInfo(clientCtx client.Context, name string) (keyring.Info, error) {
func getMultisigRecord(clientCtx client.Context, name string) (*keyring.Record, error) {
kb := clientCtx.Keyring
multisigInfo, err := kb.Key(name)
multisigRecord, err := kb.Key(name)
if err != nil {
return nil, errors.Wrap(err, "error getting keybase multisig account")
}
if multisigInfo.GetType() != keyring.TypeMulti {
return nil, fmt.Errorf("%q must be of type %s: %s", name, keyring.TypeMulti, multisigInfo.GetType())
}
return multisigInfo, nil
return multisigRecord, nil
}

View File

@ -62,8 +62,12 @@ func (s *IntegrationTestSuite) SetupSuite() {
account2, _, err := kb.NewMnemonic("newAccount2", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
s.Require().NoError(err)
pub1, err := account1.GetPubKey()
s.Require().NoError(err)
pub2, err := account2.GetPubKey()
s.Require().NoError(err)
multi := kmultisig.NewLegacyAminoPubKey(2, []cryptotypes.PubKey{account1.GetPubKey(), account2.GetPubKey()})
multi := kmultisig.NewLegacyAminoPubKey(2, []cryptotypes.PubKey{pub1, pub2})
_, err = kb.SaveMultisig("multi", multi)
s.Require().NoError(err)
@ -113,11 +117,14 @@ func (s *IntegrationTestSuite) TestCLISignGenOnly() {
val := s.network.Validators[0]
val2 := s.network.Validators[1]
info, err := val.ClientCtx.Keyring.KeyByAddress(val.Address)
k, err := val.ClientCtx.Keyring.KeyByAddress(val.Address)
s.Require().NoError(err)
keyName := info.GetName()
keyName := k.Name
account, err := val.ClientCtx.AccountRetriever.GetAccount(val.ClientCtx, info.GetAddress())
addr, err := k.GetAddress()
s.Require().NoError(err)
account, err := val.ClientCtx.AccountRetriever.GetAccount(val.ClientCtx, addr)
s.Require().NoError(err)
sendTokens := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10)))
@ -288,7 +295,7 @@ func (s *IntegrationTestSuite) TestCLISignAminoJSON() {
// SIC! validators have same key names and same addresses as those registered in the keyring,
// BUT the keys are different!
valInfo, err := val1.ClientCtx.Keyring.Key(val1.Moniker)
valRecord, err := val1.ClientCtx.Keyring.Key(val1.Moniker)
require.NoError(err)
// query account info
@ -301,7 +308,9 @@ func (s *IntegrationTestSuite) TestCLISignAminoJSON() {
res, err := TxSignExec(val1.ClientCtx, val1.Address, fileUnsigned.Name(), chainFlag,
sigOnlyFlag, signModeAminoFlag)
require.NoError(err)
checkSignatures(require, txCfg, res.Bytes(), valInfo.GetPubKey())
pub, err := valRecord.GetPubKey()
require.NoError(err)
checkSignatures(require, txCfg, res.Bytes(), pub)
sigs, err := txCfg.UnmarshalSignatureJSON(res.Bytes())
require.NoError(err)
require.Equal(1, len(sigs))
@ -333,7 +342,7 @@ func (s *IntegrationTestSuite) TestCLISignAminoJSON() {
res, err = TxSignExec(val1.ClientCtx, val1.Address, filenameSigned, chainFlag,
sigOnlyFlag, signModeAminoFlag)
require.NoError(err)
checkSignatures(require, txCfg, res.Bytes(), valInfo.GetPubKey(), valInfo.GetPubKey())
checkSignatures(require, txCfg, res.Bytes(), pub, pub)
/**** try to overwrite the previously signed transaction ****/
@ -344,7 +353,7 @@ func (s *IntegrationTestSuite) TestCLISignAminoJSON() {
res, err = TxSignExec(val1.ClientCtx, val1.Address, filenameSigned, chainFlag,
sigOnlyFlag, "--overwrite", signModeAminoFlag)
require.NoError(err)
checkSignatures(require, txCfg, res.Bytes(), valInfo.GetPubKey())
checkSignatures(require, txCfg, res.Bytes(), pub)
/**** test flagAmino ****/
res, err = TxSignExec(val1.ClientCtx, val1.Address, filenameSigned, chainFlag,
@ -355,9 +364,8 @@ func (s *IntegrationTestSuite) TestCLISignAminoJSON() {
err = val1.ClientCtx.LegacyAmino.UnmarshalJSON(res.Bytes(), &txAmino)
require.NoError(err)
require.Len(txAmino.Tx.Signatures, 2)
require.Equal(txAmino.Tx.Signatures[0].PubKey, valInfo.GetPubKey())
require.Equal(txAmino.Tx.Signatures[1].PubKey, valInfo.GetPubKey())
require.Equal(txAmino.Tx.Signatures[0].PubKey, pub)
require.Equal(txAmino.Tx.Signatures[1].PubKey, pub)
}
func checkSignatures(require *require.Assertions, txCfg client.TxConfig, output []byte, pks ...cryptotypes.PubKey) {
@ -378,9 +386,12 @@ func (s *IntegrationTestSuite) TestCLIQueryTxCmdByHash() {
sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 10)
addr, err := account2.GetAddress()
s.Require().NoError(err)
// Send coins.
out, err := s.createBankMsg(
val, account2.GetAddress(),
val, addr,
sdk.NewCoins(sendTokens),
)
s.Require().NoError(err)
@ -446,9 +457,12 @@ func (s *IntegrationTestSuite) TestCLIQueryTxCmdByEvents() {
sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 10)
addr2, err := account2.GetAddress()
s.Require().NoError(err)
// Send coins.
out, err := s.createBankMsg(
val, account2.GetAddress(),
val, addr2,
sdk.NewCoins(sendTokens),
)
s.Require().NoError(err)
@ -560,9 +574,12 @@ func (s *IntegrationTestSuite) TestCLIQueryTxsCmdByEvents() {
sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 10)
addr2, err := account2.GetAddress()
s.Require().NoError(err)
// Send coins.
out, err := s.createBankMsg(
val, account2.GetAddress(),
val,
addr2,
sdk.NewCoins(sendTokens),
)
s.Require().NoError(err)
@ -630,7 +647,9 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
sendTokens := sdk.NewCoin(s.cfg.BondDenom, sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction))
normalGeneratedTx, err := s.createBankMsg(val1, account.GetAddress(),
addr, err := account.GetAddress()
s.Require().NoError(err)
normalGeneratedTx, err := s.createBankMsg(val1, addr,
sdk.NewCoins(sendTokens), fmt.Sprintf("--%s=true", flags.FlagGenerateOnly))
s.Require().NoError(err)
@ -647,7 +666,7 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
s.Require().Equal(0, len(sigs))
// Test generate sendTx with --gas=$amount
limitedGasGeneratedTx, err := s.createBankMsg(val1, account.GetAddress(),
limitedGasGeneratedTx, err := s.createBankMsg(val1, addr,
sdk.NewCoins(sendTokens), fmt.Sprintf("--gas=%d", 100),
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly),
)
@ -672,7 +691,7 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
startTokens := balRes.Balances.AmountOf(s.cfg.BondDenom)
// Test generate sendTx, estimate gas
finalGeneratedTx, err := s.createBankMsg(val1, account.GetAddress(),
finalGeneratedTx, err := s.createBankMsg(val1, addr,
sdk.NewCoins(sendTokens), fmt.Sprintf("--gas=%d", flags.DefaultGasLimit),
fmt.Sprintf("--%s=true", flags.FlagGenerateOnly))
s.Require().NoError(err)
@ -748,7 +767,7 @@ func (s *IntegrationTestSuite) TestCLISendGenerateSignAndBroadcast() {
s.Require().NoError(s.network.WaitForNextBlock())
// Ensure destiny account state
resp, err = bankcli.QueryBalancesExec(val1.ClientCtx, account.GetAddress())
resp, err = bankcli.QueryBalancesExec(val1.ClientCtx, addr)
s.Require().NoError(err)
err = val1.ClientCtx.Codec.UnmarshalJSON(resp.Bytes(), &balRes)
@ -770,13 +789,15 @@ func (s *IntegrationTestSuite) TestCLIMultisignInsufficientCosigners() {
account1, err := val1.ClientCtx.Keyring.Key("newAccount1")
s.Require().NoError(err)
multisigInfo, err := val1.ClientCtx.Keyring.Key("multi")
multisigRecord, err := val1.ClientCtx.Keyring.Key("multi")
s.Require().NoError(err)
addr, err := multisigRecord.GetAddress()
s.Require().NoError(err)
// Send coins from validator to multisig.
_, err = s.createBankMsg(
val1,
multisigInfo.GetAddress(),
addr,
sdk.NewCoins(
sdk.NewInt64Coin(s.cfg.BondDenom, 10),
),
@ -788,7 +809,7 @@ func (s *IntegrationTestSuite) TestCLIMultisignInsufficientCosigners() {
// Generate multisig transaction.
multiGeneratedTx, err := bankcli.MsgSendExec(
val1.ClientCtx,
multisigInfo.GetAddress(),
addr,
val1.Address,
sdk.NewCoins(
sdk.NewInt64Coin(s.cfg.BondDenom, 5),
@ -805,12 +826,14 @@ func (s *IntegrationTestSuite) TestCLIMultisignInsufficientCosigners() {
// Multisign, sign with one signature
val1.ClientCtx.HomeDir = strings.Replace(val1.ClientCtx.HomeDir, "simd", "simcli", 1)
account1Signature, err := TxSignExec(val1.ClientCtx, account1.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String())
addr1, err := account1.GetAddress()
s.Require().NoError(err)
account1Signature, err := TxSignExec(val1.ClientCtx, addr1, multiGeneratedTxFile.Name(), "--multisig", addr.String())
s.Require().NoError(err)
sign1File := testutil.WriteToNewTempFile(s.T(), account1Signature.String())
multiSigWith1Signature, err := TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), sign1File.Name())
multiSigWith1Signature, err := TxMultiSignExec(val1.ClientCtx, multisigRecord.Name, multiGeneratedTxFile.Name(), sign1File.Name())
s.Require().NoError(err)
// Save tx to file
@ -861,10 +884,12 @@ func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() {
account2, err := val1.ClientCtx.Keyring.Key("newAccount2")
s.Require().NoError(err)
multisigInfo, err := val1.ClientCtx.Keyring.Key("multi")
multisigRecord, err := val1.ClientCtx.Keyring.Key("multi")
s.Require().NoError(err)
resp, err := bankcli.QueryBalancesExec(val1.ClientCtx, multisigInfo.GetAddress())
addr, err := multisigRecord.GetAddress()
s.Require().NoError(err)
resp, err := bankcli.QueryBalancesExec(val1.ClientCtx, addr)
s.Require().NoError(err)
var balRes banktypes.QueryAllBalancesResponse
@ -876,14 +901,14 @@ func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() {
sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 10)
_, err = s.createBankMsg(
val1,
multisigInfo.GetAddress(),
addr,
sdk.NewCoins(sendTokens),
)
s.Require().NoError(err)
s.Require().NoError(s.network.WaitForNextBlock())
resp, err = bankcli.QueryBalancesExec(val1.ClientCtx, multisigInfo.GetAddress())
resp, err = bankcli.QueryBalancesExec(val1.ClientCtx, addr)
s.Require().NoError(err)
err = val1.ClientCtx.Codec.UnmarshalJSON(resp.Bytes(), &balRes)
@ -894,7 +919,7 @@ func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() {
// Generate multisig transaction.
multiGeneratedTx, err := bankcli.MsgSendExec(
val1.ClientCtx,
multisigInfo.GetAddress(),
addr,
val1.Address,
sdk.NewCoins(
sdk.NewInt64Coin(s.cfg.BondDenom, 5),
@ -910,19 +935,23 @@ func (s *IntegrationTestSuite) TestCLIMultisignSortSignatures() {
multiGeneratedTxFile := testutil.WriteToNewTempFile(s.T(), multiGeneratedTx.String())
// Sign with account1
addr1, err := account1.GetAddress()
s.Require().NoError(err)
val1.ClientCtx.HomeDir = strings.Replace(val1.ClientCtx.HomeDir, "simd", "simcli", 1)
account1Signature, err := TxSignExec(val1.ClientCtx, account1.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String())
account1Signature, err := TxSignExec(val1.ClientCtx, addr1, multiGeneratedTxFile.Name(), "--multisig", addr.String())
s.Require().NoError(err)
sign1File := testutil.WriteToNewTempFile(s.T(), account1Signature.String())
// Sign with account1
account2Signature, err := TxSignExec(val1.ClientCtx, account2.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String())
addr2, err := account2.GetAddress()
s.Require().NoError(err)
account2Signature, err := TxSignExec(val1.ClientCtx, addr2, multiGeneratedTxFile.Name(), "--multisig", addr.String())
s.Require().NoError(err)
sign2File := testutil.WriteToNewTempFile(s.T(), account2Signature.String())
multiSigWith2Signatures, err := TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name())
multiSigWith2Signatures, err := TxMultiSignExec(val1.ClientCtx, multisigRecord.Name, multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name())
s.Require().NoError(err)
// Write the output to disk
@ -948,19 +977,22 @@ func (s *IntegrationTestSuite) TestCLIMultisign() {
account2, err := val1.ClientCtx.Keyring.Key("newAccount2")
s.Require().NoError(err)
multisigInfo, err := val1.ClientCtx.Keyring.Key("multi")
multisigRecord, err := val1.ClientCtx.Keyring.Key("multi")
s.Require().NoError(err)
addr, err := multisigRecord.GetAddress()
s.Require().NoError(err)
// Send coins from validator to multisig.
sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 10)
_, err = s.createBankMsg(
val1, multisigInfo.GetAddress(),
val1, addr,
sdk.NewCoins(sendTokens),
)
s.Require().NoError(err)
s.Require().NoError(s.network.WaitForNextBlock())
resp, err := bankcli.QueryBalancesExec(val1.ClientCtx, multisigInfo.GetAddress())
resp, err := bankcli.QueryBalancesExec(val1.ClientCtx, addr)
s.Require().NoError(err)
var balRes banktypes.QueryAllBalancesResponse
@ -971,7 +1003,7 @@ func (s *IntegrationTestSuite) TestCLIMultisign() {
// Generate multisig transaction.
multiGeneratedTx, err := bankcli.MsgSendExec(
val1.ClientCtx,
multisigInfo.GetAddress(),
addr,
val1.Address,
sdk.NewCoins(
sdk.NewInt64Coin(s.cfg.BondDenom, 5),
@ -986,25 +1018,29 @@ func (s *IntegrationTestSuite) TestCLIMultisign() {
// Save tx to file
multiGeneratedTxFile := testutil.WriteToNewTempFile(s.T(), multiGeneratedTx.String())
addr1, err := account1.GetAddress()
s.Require().NoError(err)
// Sign with account1
val1.ClientCtx.HomeDir = strings.Replace(val1.ClientCtx.HomeDir, "simd", "simcli", 1)
account1Signature, err := TxSignExec(val1.ClientCtx, account1.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String())
account1Signature, err := TxSignExec(val1.ClientCtx, addr1, multiGeneratedTxFile.Name(), "--multisig", addr.String())
s.Require().NoError(err)
sign1File := testutil.WriteToNewTempFile(s.T(), account1Signature.String())
// Sign with account2
account2Signature, err := TxSignExec(val1.ClientCtx, account2.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String())
addr2, err := account2.GetAddress()
s.Require().NoError(err)
// Sign with account1
account2Signature, err := TxSignExec(val1.ClientCtx, addr2, multiGeneratedTxFile.Name(), "--multisig", addr.String())
s.Require().NoError(err)
sign2File := testutil.WriteToNewTempFile(s.T(), account2Signature.String())
// Does not work in offline mode.
_, err = TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), "--offline", sign1File.Name(), sign2File.Name())
s.Require().EqualError(err, fmt.Sprintf("couldn't verify signature for address %s", account1.GetAddress()))
_, err = TxMultiSignExec(val1.ClientCtx, multisigRecord.Name, multiGeneratedTxFile.Name(), "--offline", sign1File.Name(), sign2File.Name())
s.Require().EqualError(err, fmt.Sprintf("couldn't verify signature for address %s", addr1))
val1.ClientCtx.Offline = false
multiSigWith2Signatures, err := TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name())
multiSigWith2Signatures, err := TxMultiSignExec(val1.ClientCtx, multisigRecord.Name, multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name())
s.Require().NoError(err)
// Write the output to disk
@ -1028,14 +1064,16 @@ func (s *IntegrationTestSuite) TestSignBatchMultisig() {
s.Require().NoError(err)
account2, err := val.ClientCtx.Keyring.Key("newAccount2")
s.Require().NoError(err)
multisigInfo, err := val.ClientCtx.Keyring.Key("multi")
multisigRecord, err := val.ClientCtx.Keyring.Key("multi")
s.Require().NoError(err)
addr, err := multisigRecord.GetAddress()
s.Require().NoError(err)
// Send coins from validator to multisig.
sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 10)
_, err = s.createBankMsg(
val,
multisigInfo.GetAddress(),
addr,
sdk.NewCoins(sendTokens),
)
s.Require().NoError(err)
@ -1043,7 +1081,7 @@ func (s *IntegrationTestSuite) TestSignBatchMultisig() {
generatedStd, err := bankcli.MsgSendExec(
val.ClientCtx,
multisigInfo.GetAddress(),
addr,
val.Address,
sdk.NewCoins(
sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(1)),
@ -1059,28 +1097,24 @@ func (s *IntegrationTestSuite) TestSignBatchMultisig() {
filename := testutil.WriteToNewTempFile(s.T(), strings.Repeat(generatedStd.String(), 1))
val.ClientCtx.HomeDir = strings.Replace(val.ClientCtx.HomeDir, "simd", "simcli", 1)
addr1, err := account1.GetAddress()
s.Require().NoError(err)
// sign-batch file
res, err := TxSignBatchExec(val.ClientCtx, account1.GetAddress(), filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", multisigInfo.GetAddress().String())
res, err := TxSignBatchExec(val.ClientCtx, addr1, filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", addr.String())
s.Require().NoError(err)
s.Require().Equal(1, len(strings.Split(strings.Trim(res.String(), "\n"), "\n")))
// write sigs to file
file1 := testutil.WriteToNewTempFile(s.T(), res.String())
addr2, err := account2.GetAddress()
s.Require().NoError(err)
// sign-batch file with account2
res, err = TxSignBatchExec(val.ClientCtx, account2.GetAddress(), filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", multisigInfo.GetAddress().String())
res, err = TxSignBatchExec(val.ClientCtx, addr2, filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", addr.String())
s.Require().NoError(err)
s.Require().Equal(1, len(strings.Split(strings.Trim(res.String(), "\n"), "\n")))
// write sigs to file2
file2 := testutil.WriteToNewTempFile(s.T(), res.String())
// sign-batch file with multisig key name
res, err = TxSignBatchExec(val.ClientCtx, account1.GetAddress(), filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", multisigInfo.GetName())
s.Require().NoError(err)
s.Require().Equal(1, len(strings.Split(strings.Trim(res.String(), "\n"), "\n")))
// write sigs to file3
file3 := testutil.WriteToNewTempFile(s.T(), res.String())
_, err = TxMultiSignExec(val.ClientCtx, multisigInfo.GetName(), filename.Name(), file1.Name(), file2.Name(), file3.Name())
_, err = TxMultiSignExec(val.ClientCtx, multisigRecord.Name, filename.Name(), file1.Name(), file2.Name())
s.Require().NoError(err)
}
@ -1093,14 +1127,16 @@ func (s *IntegrationTestSuite) TestMultisignBatch() {
s.Require().NoError(err)
account2, err := val.ClientCtx.Keyring.Key("newAccount2")
s.Require().NoError(err)
multisigInfo, err := val.ClientCtx.Keyring.Key("multi")
multisigRecord, err := val.ClientCtx.Keyring.Key("multi")
s.Require().NoError(err)
addr, err := multisigRecord.GetAddress()
s.Require().NoError(err)
// Send coins from validator to multisig.
sendTokens := sdk.NewInt64Coin(s.cfg.BondDenom, 1000)
_, err = s.createBankMsg(
val,
multisigInfo.GetAddress(),
addr,
sdk.NewCoins(sendTokens),
)
s.Require().NoError(err)
@ -1108,7 +1144,7 @@ func (s *IntegrationTestSuite) TestMultisignBatch() {
generatedStd, err := bankcli.MsgSendExec(
val.ClientCtx,
multisigInfo.GetAddress(),
addr,
val.Address,
sdk.NewCoins(
sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(1)),
@ -1124,34 +1160,30 @@ func (s *IntegrationTestSuite) TestMultisignBatch() {
filename := testutil.WriteToNewTempFile(s.T(), strings.Repeat(generatedStd.String(), 3))
val.ClientCtx.HomeDir = strings.Replace(val.ClientCtx.HomeDir, "simd", "simcli", 1)
queryResJSON, err := QueryAccountExec(val.ClientCtx, multisigInfo.GetAddress())
queryResJSON, err := QueryAccountExec(val.ClientCtx, addr)
s.Require().NoError(err)
var account authtypes.AccountI
s.Require().NoError(val.ClientCtx.Codec.UnmarshalInterfaceJSON(queryResJSON.Bytes(), &account))
// sign-batch file
res, err := TxSignBatchExec(val.ClientCtx, account1.GetAddress(), filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", multisigInfo.GetAddress().String(), fmt.Sprintf("--%s", flags.FlagOffline), fmt.Sprintf("--%s=%s", flags.FlagAccountNumber, fmt.Sprint(account.GetAccountNumber())), fmt.Sprintf("--%s=%s", flags.FlagSequence, fmt.Sprint(account.GetSequence())))
addr1, err := account1.GetAddress()
s.Require().NoError(err)
res, err := TxSignBatchExec(val.ClientCtx, addr1, filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", addr.String(), fmt.Sprintf("--%s", flags.FlagOffline), fmt.Sprintf("--%s=%s", flags.FlagAccountNumber, fmt.Sprint(account.GetAccountNumber())), fmt.Sprintf("--%s=%s", flags.FlagSequence, fmt.Sprint(account.GetSequence())))
s.Require().NoError(err)
s.Require().Equal(3, len(strings.Split(strings.Trim(res.String(), "\n"), "\n")))
// write sigs to file
file1 := testutil.WriteToNewTempFile(s.T(), res.String())
// sign-batch file with account2
res, err = TxSignBatchExec(val.ClientCtx, account2.GetAddress(), filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", multisigInfo.GetAddress().String(), fmt.Sprintf("--%s", flags.FlagOffline), fmt.Sprintf("--%s=%s", flags.FlagAccountNumber, fmt.Sprint(account.GetAccountNumber())), fmt.Sprintf("--%s=%s", flags.FlagSequence, fmt.Sprint(account.GetSequence())))
addr2, err := account2.GetAddress()
s.Require().NoError(err)
res, err = TxSignBatchExec(val.ClientCtx, addr2, filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", addr.String(), fmt.Sprintf("--%s", flags.FlagOffline), fmt.Sprintf("--%s=%s", flags.FlagAccountNumber, fmt.Sprint(account.GetAccountNumber())), fmt.Sprintf("--%s=%s", flags.FlagSequence, fmt.Sprint(account.GetSequence())))
s.Require().NoError(err)
s.Require().Equal(3, len(strings.Split(strings.Trim(res.String(), "\n"), "\n")))
// multisign the file
file2 := testutil.WriteToNewTempFile(s.T(), res.String())
// sign-batch file with multisig key name
res, err = TxSignBatchExec(val.ClientCtx, account1.GetAddress(), filename.Name(), fmt.Sprintf("--%s=%s", flags.FlagChainID, val.ClientCtx.ChainID), "--multisig", multisigInfo.GetName(), fmt.Sprintf("--%s", flags.FlagOffline), fmt.Sprintf("--%s=%s", flags.FlagAccountNumber, fmt.Sprint(account.GetAccountNumber())), fmt.Sprintf("--%s=%s", flags.FlagSequence, fmt.Sprint(account.GetSequence())))
s.Require().NoError(err)
s.Require().Equal(3, len(strings.Split(strings.Trim(res.String(), "\n"), "\n")))
// write sigs to file
file3 := testutil.WriteToNewTempFile(s.T(), res.String())
res, err = TxMultiSignBatchExec(val.ClientCtx, filename.Name(), multisigInfo.GetName(), file1.Name(), file2.Name(), file3.Name())
res, err = TxMultiSignBatchExec(val.ClientCtx, filename.Name(), multisigRecord.Name, file1.Name(), file2.Name())
s.Require().NoError(err)
signedTxs := strings.Split(strings.Trim(res.String(), "\n"), "\n")

View File

@ -34,18 +34,22 @@ func (gr GasEstimateResponse) String() string {
// The new signature is appended to the TxBuilder when overwrite=false or overwritten otherwise.
// Don't perform online validation or lookups if offline is true.
func SignTx(txFactory tx.Factory, clientCtx client.Context, name string, txBuilder client.TxBuilder, offline, overwriteSig bool) error {
info, err := txFactory.Keybase().Key(name)
k, err := txFactory.Keybase().Key(name)
if err != nil {
return err
}
// Ledger and Multisigs only support LEGACY_AMINO_JSON signing.
if txFactory.SignMode() == signing.SignMode_SIGN_MODE_UNSPECIFIED &&
(info.GetType() == keyring.TypeLedger || info.GetType() == keyring.TypeMulti) {
(k.GetType() == keyring.TypeLedger || k.GetType() == keyring.TypeMulti) {
txFactory = txFactory.WithSignMode(signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON)
}
addr := sdk.AccAddress(info.GetPubKey().Address())
pubKey, err := k.GetPubKey()
if err != nil {
return err
}
addr := sdk.AccAddress(pubKey.Address())
if !isTxSigner(addr, txBuilder.GetTx().GetSigners()) {
return fmt.Errorf("%s: %s", sdkerrors.ErrorInvalidSigner, name)
}

View File

@ -494,26 +494,35 @@ func (s *IntegrationTestSuite) TestSimMultiSigTx() {
account2, _, err := kr.NewMnemonic("newAccount2", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
s.Require().NoError(err)
multi := kmultisig.NewLegacyAminoPubKey(2, []cryptotypes.PubKey{account1.GetPubKey(), account2.GetPubKey()})
pub1, err := account1.GetPubKey()
s.Require().NoError(err)
pub2, err := account2.GetPubKey()
s.Require().NoError(err)
multi := kmultisig.NewLegacyAminoPubKey(2, []cryptotypes.PubKey{pub1, pub2})
_, err = kr.SaveMultisig("multi", multi)
s.Require().NoError(err)
_, err = s.network.WaitForHeight(1)
s.Require().NoError(err)
multisigInfo, err := val1.ClientCtx.Keyring.Key("multi")
multisigRecord, err := val1.ClientCtx.Keyring.Key("multi")
s.Require().NoError(err)
height, err := s.network.LatestHeight()
_, err = s.network.WaitForHeight(height + 1)
s.Require().NoError(err)
addr, err := multisigRecord.GetAddress()
s.Require().NoError(err)
// Send coins from validator to multisig.
coins := sdk.NewInt64Coin(s.cfg.BondDenom, 15)
_, err = bankcli.MsgSendExec(
val1.ClientCtx,
val1.Address,
multisigInfo.GetAddress(),
addr,
sdk.NewCoins(coins),
fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
@ -528,7 +537,7 @@ func (s *IntegrationTestSuite) TestSimMultiSigTx() {
// Generate multisig transaction.
multiGeneratedTx, err := bankcli.MsgSendExec(
val1.ClientCtx,
multisigInfo.GetAddress(),
addr,
val1.Address,
sdk.NewCoins(
sdk.NewInt64Coin(s.cfg.BondDenom, 5),
@ -545,19 +554,23 @@ func (s *IntegrationTestSuite) TestSimMultiSigTx() {
multiGeneratedTxFile := testutil.WriteToNewTempFile(s.T(), multiGeneratedTx.String())
// Sign with account1
addr1, err := account1.GetAddress()
s.Require().NoError(err)
val1.ClientCtx.HomeDir = strings.Replace(val1.ClientCtx.HomeDir, "simd", "simcli", 1)
account1Signature, err := authtest.TxSignExec(val1.ClientCtx, account1.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String())
account1Signature, err := authtest.TxSignExec(val1.ClientCtx, addr1, multiGeneratedTxFile.Name(), "--multisig", addr.String())
s.Require().NoError(err)
sign1File := testutil.WriteToNewTempFile(s.T(), account1Signature.String())
// Sign with account2
account2Signature, err := authtest.TxSignExec(val1.ClientCtx, account2.GetAddress(), multiGeneratedTxFile.Name(), "--multisig", multisigInfo.GetAddress().String())
addr2, err := account2.GetAddress()
s.Require().NoError(err)
account2Signature, err := authtest.TxSignExec(val1.ClientCtx, addr2, multiGeneratedTxFile.Name(), "--multisig", addr.String())
s.Require().NoError(err)
sign2File := testutil.WriteToNewTempFile(s.T(), account2Signature.String())
// multisign tx
val1.ClientCtx.Offline = false
multiSigWith2Signatures, err := authtest.TxMultiSignExec(val1.ClientCtx, multisigInfo.GetName(), multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name())
multiSigWith2Signatures, err := authtest.TxMultiSignExec(val1.ClientCtx, multisigRecord.Name, multiGeneratedTxFile.Name(), sign1File.Name(), sign2File.Name())
s.Require().NoError(err)
// convert from protoJSON to protoBinary for sim

View File

@ -45,9 +45,9 @@ func (s *IntegrationTestSuite) SetupSuite() {
val := s.network.Validators[0]
s.grantee = make([]sdk.AccAddress, 2)
// Send some funds to the new account.
// Create new account in the keyring.
s.grantee[0] = s.createAccount("grantee1")
// Send some funds to the new account.
s.msgSendExec(s.grantee[0])
_, err = s.network.WaitForHeight(1)
s.Require().NoError(err)
@ -84,9 +84,13 @@ func (s *IntegrationTestSuite) SetupSuite() {
func (s *IntegrationTestSuite) createAccount(uid string) sdk.AccAddress {
val := s.network.Validators[0]
// Create new account in the keyring.
info, _, err := val.ClientCtx.Keyring.NewMnemonic(uid, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
k, _, err := val.ClientCtx.Keyring.NewMnemonic(uid, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
s.Require().NoError(err)
return sdk.AccAddress(info.GetPubKey().Address())
addr, err := k.GetAddress()
s.Require().NoError(err)
return addr
}
func (s *IntegrationTestSuite) msgSendExec(grantee sdk.AccAddress) {

View File

@ -661,9 +661,11 @@ func (s *IntegrationTestSuite) TestTxWithFeeGrant() {
granter := val.Address
// creating an account manually (This account won't be exist in state)
info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
k, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
s.Require().NoError(err)
grantee := sdk.AccAddress(info.GetPubKey().Address())
pub, err := k.GetPubKey()
s.Require().NoError(err)
grantee := sdk.AccAddress(pub.Address())
commonFlags := []string{
fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock),
@ -708,9 +710,11 @@ func (s *IntegrationTestSuite) TestFilteredFeeAllowance() {
val := s.network.Validators[0]
granter := val.Address
info, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee1", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
k, _, err := val.ClientCtx.Keyring.NewMnemonic("grantee1", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
s.Require().NoError(err)
grantee := sdk.AccAddress(info.GetPubKey().Address())
pub, err := k.GetPubKey()
s.Require().NoError(err)
grantee := sdk.AccAddress(pub.Address())
clientCtx := val.ClientCtx

View File

@ -121,8 +121,11 @@ $ %s gentx my-key-name 1000000stake --home=/path/to/home/dir --keyring-backend=o
if err != nil {
return errors.Wrap(err, "failed to parse coins")
}
err = genutil.ValidateAccountInGenesis(genesisState, genBalIterator, key.GetAddress(), coins, cdc)
addr, err := key.GetAddress()
if err != nil {
return err
}
err = genutil.ValidateAccountInGenesis(genesisState, genBalIterator, addr, coins, cdc)
if err != nil {
return errors.Wrap(err, "failed to validate account in genesis")
}
@ -131,8 +134,11 @@ $ %s gentx my-key-name 1000000stake --home=/path/to/home/dir --keyring-backend=o
if err != nil {
return errors.Wrap(err, "error creating tx builder")
}
clientCtx = clientCtx.WithInput(inBuf).WithFromAddress(key.GetAddress())
pub, err := key.GetAddress()
if err != nil {
return err
}
clientCtx = clientCtx.WithInput(inBuf).WithFromAddress(pub)
// The following line comes from a discrepancy between the `gentx`
// and `create-validator` commands:

View File

@ -2,13 +2,14 @@ package genutil
import (
"encoding/json"
tmed25519 "github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/privval"
"os"
"path/filepath"
"testing"
"time"
tmed25519 "github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/privval"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/config"
)

View File

@ -4,13 +4,14 @@ import (
"fmt"
"time"
"github.com/stretchr/testify/suite"
tmcli "github.com/tendermint/tendermint/libs/cli"
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
"github.com/cosmos/cosmos-sdk/testutil/network"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/gov/client/cli"
"github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/stretchr/testify/suite"
tmcli "github.com/tendermint/tendermint/libs/cli"
)
type DepositTestSuite struct {

View File

@ -359,9 +359,10 @@ func (s *IntegrationTestSuite) TestGRPCQueryDelegatorDelegations() {
baseURL := val.APIAddress
// Create new account in the keyring for address without delegations.
info, _, err := val.ClientCtx.Keyring.NewMnemonic("test", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
k, _, err := val.ClientCtx.Keyring.NewMnemonic("test", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
s.Require().NoError(err)
newAddr, err := k.GetAddress()
s.Require().NoError(err)
newAddr := sdk.AccAddress(info.GetPubKey().Address())
testCases := []struct {
name string

View File

@ -93,10 +93,13 @@ func (s *IntegrationTestSuite) TestNewCreateValidatorCmd() {
require.NoError(err)
require.NotNil(consPubKeyBz)
info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewValidator", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
k, _, err := val.ClientCtx.Keyring.NewMnemonic("NewValidator", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
require.NoError(err)
newAddr := sdk.AccAddress(info.GetPubKey().Address())
pub, err := k.GetPubKey()
require.NoError(err)
newAddr := sdk.AccAddress(pub.Address())
_, err = banktestutil.MsgSendExec(
val.ClientCtx,
val.Address,
@ -1058,10 +1061,13 @@ func (s *IntegrationTestSuite) TestNewEditValidatorCmd() {
func (s *IntegrationTestSuite) TestNewDelegateCmd() {
val := s.network.Validators[0]
info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
k, _, err := val.ClientCtx.Keyring.NewMnemonic("NewAccount", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
s.Require().NoError(err)
newAddr := sdk.AccAddress(info.GetPubKey().Address())
pub, err := k.GetPubKey()
s.Require().NoError(err)
newAddr := sdk.AccAddress(pub.Address())
_, err = banktestutil.MsgSendExec(
val.ClientCtx,
@ -1298,9 +1304,11 @@ func (s *IntegrationTestSuite) TestBlockResults() {
val := s.network.Validators[0]
// Create new account in the keyring.
info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewDelegator", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
k, _, err := val.ClientCtx.Keyring.NewMnemonic("NewDelegator", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
require.NoError(err)
newAddr := sdk.AccAddress(info.GetPubKey().Address())
pub, err := k.GetPubKey()
require.NoError(err)
newAddr := sdk.AccAddress(pub.Address())
// Send some funds to the new account.
_, err = banktestutil.MsgSendExec(

View File

@ -4,7 +4,7 @@ import (
"context"
"time"
metrics "github.com/armon/go-metrics"
"github.com/armon/go-metrics"
tmstrings "github.com/tendermint/tendermint/libs/strings"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"

View File

@ -5,8 +5,9 @@ package testutil
import (
"testing"
"github.com/cosmos/cosmos-sdk/testutil/network"
"github.com/stretchr/testify/suite"
"github.com/cosmos/cosmos-sdk/testutil/network"
)
func TestIntegrationTestSuite(t *testing.T) {

View File

@ -3,14 +3,15 @@ package testutil
import (
"fmt"
"github.com/stretchr/testify/suite"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/cosmos/cosmos-sdk/simapp"
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
"github.com/cosmos/cosmos-sdk/testutil/network"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/upgrade/client/cli"
"github.com/cosmos/cosmos-sdk/x/upgrade/types"
"github.com/stretchr/testify/suite"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
)
func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite {