From 705a417526bcff287a3963081373c32a3b3de22a Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 26 Mar 2020 11:40:29 +0100 Subject: [PATCH 001/148] New keyring interface WIP --- crypto/keyring/keyring.go | 64 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 3db8c3d433a..926d4515f56 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -14,6 +14,7 @@ import ( "github.com/pkg/errors" "github.com/tendermint/crypto/bcrypt" + "github.com/tendermint/tendermint/crypto" tmcrypto "github.com/tendermint/tendermint/crypto" cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" @@ -39,6 +40,69 @@ const ( var _ Keybase = keyringKeybase{} +// Keyring exposes operations on a generic keystore +type Keyring interface { + + // List all keys. + List() ([]Info, error) + + // Key and KeyByAddress return keys by uid and address respectively. + Key(uid string) (Info, error) + KeyByAddress(address types.Address) (Info, error) + + // Delete and DeleteByAddress remove keys. + Delete(uid string) error + DeleteByAddress(address types.Address) error + + // NewMnemonic generates a new mnemonic, derives a hierarchical deterministic + // key from that, and persists it to storage. Returns the generated mnemonic and the key + // Info. It returns an error if it fails to generate a key for the given algo type, or if + // another key is already stored under the same name. + NewMnemonic(uid string, language Language, algo SigningAlgo) (Info, string, error) + + // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. + NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SigningAlgo) (Info, error) + + // SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. + SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) + + // SavePubKey stores a public key and returns the persisted Info structure. + SavePubKey(uid string, pubkey crypto.PubKey, algo SigningAlgo) (Info, error) + + // SaveMultisig stores, stores, and returns a new multsig (offline) key reference + SaveMultisig(uid string, pubkey crypto.PubKey) (Info, error) + + // SupportedAlgos returns a list of signing algorithms supported by the keybase + SupportedAlgos() []SigningAlgo + + // SupportedAlgosLedger returns a list of signing algorithms supported by the keybase's ledger integration + SupportedAlgosLedger() []SigningAlgo +} + +// Signer is implemented by key stores that want to provide signing capabilities. +type Signer interface { + // Sign and SignByAddress sign byte messages with a user key. + Sign(uid string, msg []byte) ([]byte, crypto.PubKey, error) + SignByAddress(address types.Address, msg []byte) ([]byte, crypto.PubKey, error) +} + +// Importer is implemented by key stores that support import of public and private keys. +type Importer interface { + ImportPrivKey(uid, armor, passphrase string) error + ImportPubKey(uid string, armor string) error +} + +// Exporter is implemented by key stores that support export of public and private keys. +type Exporter interface { + // Export public key + ExportPubKeyArmor(uid string) (string, error) + ExportPubKeyArmorByAddress(address types.Address) (string, error) + // 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. + ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) + ExportPrivKeyArmorByAddress(address types.Address, encryptPassphrase string) (armor string, err error) +} + // keyringKeybase implements the Keybase interface by using the Keyring library // for account key persistence. type keyringKeybase struct { From 13a973d50452b63b50b6bc1139ba67e636083395 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 26 Mar 2020 17:59:04 +0100 Subject: [PATCH 002/148] temp commit --- crypto/keyring/altkeyring.go | 103 ++++++++++++++++++++++++++++++ crypto/keyring/altkeyring_test.go | 1 + crypto/keyring/keyring.go | 46 ++++++------- 3 files changed, 127 insertions(+), 23 deletions(-) create mode 100644 crypto/keyring/altkeyring.go create mode 100644 crypto/keyring/altkeyring_test.go diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go new file mode 100644 index 00000000000..12f2b6d7cff --- /dev/null +++ b/crypto/keyring/altkeyring.go @@ -0,0 +1,103 @@ +package keyring + +import ( + "github.com/99designs/keyring" + "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/go-bip39" + tmcrypto "github.com/tendermint/tendermint/crypto" +) + +var ( + _ Keyring = &altKeyring{} +) + +type altKeyring struct { + db keyring.Keyring +} + +func (a altKeyring) List() ([]Info, error) { + panic("implement me") +} + +func (a altKeyring) NewMnemonic(uid string, language Language, algo SigningAlgo) (Info, string, error) { + if language != English { + return nil, "", ErrUnsupportedLanguage + } + + //if !IsSupportedAlgorithm(a.SupportedAlgos(), algo) { + // return nil, "", ErrUnsupportedSigningAlgo + //} + + // Default number of words (24): This generates a mnemonic directly from the + // number of words by reading system entropy. + entropy, err := bip39.NewEntropy(defaultEntropySize) + if err != nil { + return nil, "", err + } + + mnemonic, err := bip39.NewMnemonic(entropy) + if err != nil { + return nil, "", err + } + + info, err := a.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), algo) + if err != nil { + return nil, "", err + } + + return info, mnemonic, err +} + +func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase string, hdPath string, algo SigningAlgo) (Info, error) { + // create master key and derive first key for keyring + derivedPriv, err := StdDeriveKey(mnemonic, bip39Passphrase, hdPath, algo) + if err != nil { + return nil, err + } + + privKey, err := StdPrivKeyGen(derivedPriv, algo) + if err != nil { + return nil, err + } + + var info Info + + //if encryptPasswd != "" { + info = a.writeLocalKey(uid, privKey, encryptPasswd, algo) + //} else { + // info = a.writeOfflineKey(keyWriter, name, privKey.PubKey(), algo) + //} + + return info, nil +} + +func (a altKeyring) writeLocalKey(name string, priv tmcrypto.PrivKey, _ string, algo SigningAlgo) Info { + // encrypt private key using keyring + pub := priv.PubKey() + info := newLocalInfo(name, pub, string(priv.Bytes()), algo) + + a.writeInfo(name, info) + return info +} + +func (a altKeyring) writeInfo(name string, info Info) { + // write the info by key + key := infoKey(name) + serializedInfo := marshalInfo(info) + + err := a.db.Set(keyring.Item{ + Key: string(key), + Data: serializedInfo, + }) + if err != nil { + panic(err) + } + + err = a.db.Set(keyring.Item{ + Key: string(addrKey(info.GetAddress())), + Data: key, + }) + if err != nil { + panic(err) + } +} diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go new file mode 100644 index 00000000000..cc6ea738dcf --- /dev/null +++ b/crypto/keyring/altkeyring_test.go @@ -0,0 +1 @@ +package keyring diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 926d4515f56..ffa3af87ca6 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -42,18 +42,17 @@ var _ Keybase = keyringKeybase{} // Keyring exposes operations on a generic keystore type Keyring interface { - // List all keys. List() ([]Info, error) - // Key and KeyByAddress return keys by uid and address respectively. - Key(uid string) (Info, error) - KeyByAddress(address types.Address) (Info, error) - - // Delete and DeleteByAddress remove keys. - Delete(uid string) error - DeleteByAddress(address types.Address) error - + //// Key and KeyByAddress return keys by uid and address respectively. + //Key(uid string) (Info, error) + //KeyByAddress(address types.Address) (Info, error) + // + //// Delete and DeleteByAddress remove keys. + //Delete(uid string) error + //DeleteByAddress(address types.Address) error + // // NewMnemonic generates a new mnemonic, derives a hierarchical deterministic // key from that, and persists it to storage. Returns the generated mnemonic and the key // Info. It returns an error if it fails to generate a key for the given algo type, or if @@ -63,20 +62,21 @@ type Keyring interface { // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SigningAlgo) (Info, error) - // SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. - SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) - - // SavePubKey stores a public key and returns the persisted Info structure. - SavePubKey(uid string, pubkey crypto.PubKey, algo SigningAlgo) (Info, error) - - // SaveMultisig stores, stores, and returns a new multsig (offline) key reference - SaveMultisig(uid string, pubkey crypto.PubKey) (Info, error) - - // SupportedAlgos returns a list of signing algorithms supported by the keybase - SupportedAlgos() []SigningAlgo - - // SupportedAlgosLedger returns a list of signing algorithms supported by the keybase's ledger integration - SupportedAlgosLedger() []SigningAlgo + // + //// SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. + //SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) + // + //// SavePubKey stores a public key and returns the persisted Info structure. + //SavePubKey(uid string, pubkey crypto.PubKey, algo SigningAlgo) (Info, error) + // + //// SaveMultisig stores, stores, and returns a new multsig (offline) key reference + //SaveMultisig(uid string, pubkey crypto.PubKey) (Info, error) + // + //// SupportedAlgos returns a list of signing algorithms supported by the keybase + //SupportedAlgos() []SigningAlgo + // + //// SupportedAlgosLedger returns a list of signing algorithms supported by the keybase's ledger integration + //SupportedAlgosLedger() []SigningAlgo } // Signer is implemented by key stores that want to provide signing capabilities. From d5c201814bb2502730fe7ca1c543cec7e9a66ce7 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 26 Mar 2020 21:55:40 +0100 Subject: [PATCH 003/148] temp commit --- crypto/keyring/altkeyring.go | 11 ++++------- crypto/keyring/altkeyring_test.go | 5 +++++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 12f2b6d7cff..0cce8b69a63 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -62,21 +62,18 @@ func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase stri var info Info - //if encryptPasswd != "" { - info = a.writeLocalKey(uid, privKey, encryptPasswd, algo) - //} else { - // info = a.writeOfflineKey(keyWriter, name, privKey.PubKey(), algo) - //} + info = a.writeLocalKey(uid, privKey, algo) return info, nil } -func (a altKeyring) writeLocalKey(name string, priv tmcrypto.PrivKey, _ string, algo SigningAlgo) Info { +func (a altKeyring) writeLocalKey(name string, priv tmcrypto.PrivKey, algo SigningAlgo) Info { // encrypt private key using keyring pub := priv.PubKey() - info := newLocalInfo(name, pub, string(priv.Bytes()), algo) + info := newLocalInfo(name, pub, string(priv.Bytes()), algo) a.writeInfo(name, info) + return info } diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index cc6ea738dcf..7be6d2cff8e 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -1 +1,6 @@ package keyring + +import "testing" + +func TestAltKeyring_List(t *testing.T) { +} \ No newline at end of file From 1baf2b68fa5aeadabfb8778653701c1dfbbeaacb Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 26 Mar 2020 22:33:46 +0100 Subject: [PATCH 004/148] add test for list --- crypto/keyring/altkeyring.go | 132 +++++++++++++++++++++++++++++- crypto/keyring/altkeyring_test.go | 19 ++++- crypto/keyring/keyring.go | 64 --------------- 3 files changed, 148 insertions(+), 67 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 0cce8b69a63..dc9ee58bc17 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -1,6 +1,13 @@ package keyring import ( + "fmt" + "io" + "sort" + "strings" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/99designs/keyring" "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/go-bip39" @@ -11,12 +18,135 @@ var ( _ Keyring = &altKeyring{} ) +// Keyring exposes operations on a generic keystore +type Keyring interface { + // List all keys. + List() ([]Info, error) + + //// Key and KeyByAddress return keys by uid and address respectively. + //Key(uid string) (Info, error) + //KeyByAddress(address types.Address) (Info, error) + // + //// Delete and DeleteByAddress remove keys. + //Delete(uid string) error + //DeleteByAddress(address types.Address) error + + // NewMnemonic generates a new mnemonic, derives a hierarchical deterministic + // key from that, and persists it to storage. Returns the generated mnemonic and the key + // Info. It returns an error if it fails to generate a key for the given algo type, or if + // another key is already stored under the same name. + NewMnemonic(uid string, language Language, algo SigningAlgo) (Info, string, error) + + // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. + NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SigningAlgo) (Info, error) + + // + //// SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. + //SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) + // + //// SavePubKey stores a public key and returns the persisted Info structure. + //SavePubKey(uid string, pubkey crypto.PubKey, algo SigningAlgo) (Info, error) + // + //// SaveMultisig stores, stores, and returns a new multsig (offline) key reference + //SaveMultisig(uid string, pubkey crypto.PubKey) (Info, error) + // + //// SupportedAlgos returns a list of signing algorithms supported by the keybase + //SupportedAlgos() []SigningAlgo + // + //// SupportedAlgosLedger returns a list of signing algorithms supported by the keybase's ledger integration + //SupportedAlgosLedger() []SigningAlgo +} + +// Signer is implemented by key stores that want to provide signing capabilities. +type Signer interface { + // Sign and SignByAddress sign byte messages with a user key. + Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error) + SignByAddress(address types.Address, msg []byte) ([]byte, tmcrypto.PubKey, error) +} + +// Importer is implemented by key stores that support import of public and private keys. +type Importer interface { + ImportPrivKey(uid, armor, passphrase string) error + ImportPubKey(uid string, armor string) error +} + +// Exporter is implemented by key stores that support export of public and private keys. +type Exporter interface { + // Export public key + ExportPubKeyArmor(uid string) (string, error) + ExportPubKeyArmorByAddress(address types.Address) (string, error) + // 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. + ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) + ExportPrivKeyArmorByAddress(address types.Address, encryptPassphrase string) (armor string, err error) +} + +// NewKeyring creates a new instance of a keyring. Keybase +// options can be applied when generating this new Keybase. +// Available backends are "os", "file", "kwallet", "pass", "test". +func NewAltKeyring( + appName, backend, rootDir string, userInput io.Reader, opts ...KeybaseOption, +) (Keyring, error) { + + var db keyring.Keyring + var err error + + switch backend { + case BackendTest: + db, err = keyring.Open(lkbToKeyringConfig(appName, rootDir, nil, true)) + case BackendFile: + db, err = keyring.Open(newFileBackendKeyringConfig(appName, rootDir, userInput)) + case BackendOS: + db, err = keyring.Open(lkbToKeyringConfig(appName, rootDir, userInput, false)) + case BackendKWallet: + db, err = keyring.Open(newKWalletBackendKeyringConfig(appName, rootDir, userInput)) + case BackendPass: + db, err = keyring.Open(newPassBackendKeyringConfig(appName, rootDir, userInput)) + default: + return nil, fmt.Errorf("unknown keyring backend %v", backend) + } + + if err != nil { + return nil, err + } + + return altKeyring{db: db}, nil +} + type altKeyring struct { db keyring.Keyring } func (a altKeyring) List() ([]Info, error) { - panic("implement me") + var res []Info + keys, err := a.db.Keys() + if err != nil { + return nil, err + } + + sort.Strings(keys) + + for _, key := range keys { + if strings.HasSuffix(key, infoSuffix) { + rawInfo, err := a.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) + } + } + + return res, nil } func (a altKeyring) NewMnemonic(uid string, language Language, algo SigningAlgo) (Info, string, error) { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 7be6d2cff8e..b7a623f5032 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -1,6 +1,21 @@ package keyring -import "testing" +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/tests" +) func TestAltKeyring_List(t *testing.T) { -} \ No newline at end of file + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + list, err := keyring.List() + require.NoError(t, err) + require.Len(t, list, 0) +} diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index ffa3af87ca6..3db8c3d433a 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -14,7 +14,6 @@ import ( "github.com/pkg/errors" "github.com/tendermint/crypto/bcrypt" - "github.com/tendermint/tendermint/crypto" tmcrypto "github.com/tendermint/tendermint/crypto" cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" @@ -40,69 +39,6 @@ const ( var _ Keybase = keyringKeybase{} -// Keyring exposes operations on a generic keystore -type Keyring interface { - // List all keys. - List() ([]Info, error) - - //// Key and KeyByAddress return keys by uid and address respectively. - //Key(uid string) (Info, error) - //KeyByAddress(address types.Address) (Info, error) - // - //// Delete and DeleteByAddress remove keys. - //Delete(uid string) error - //DeleteByAddress(address types.Address) error - // - // NewMnemonic generates a new mnemonic, derives a hierarchical deterministic - // key from that, and persists it to storage. Returns the generated mnemonic and the key - // Info. It returns an error if it fails to generate a key for the given algo type, or if - // another key is already stored under the same name. - NewMnemonic(uid string, language Language, algo SigningAlgo) (Info, string, error) - - // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. - NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SigningAlgo) (Info, error) - - // - //// SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. - //SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) - // - //// SavePubKey stores a public key and returns the persisted Info structure. - //SavePubKey(uid string, pubkey crypto.PubKey, algo SigningAlgo) (Info, error) - // - //// SaveMultisig stores, stores, and returns a new multsig (offline) key reference - //SaveMultisig(uid string, pubkey crypto.PubKey) (Info, error) - // - //// SupportedAlgos returns a list of signing algorithms supported by the keybase - //SupportedAlgos() []SigningAlgo - // - //// SupportedAlgosLedger returns a list of signing algorithms supported by the keybase's ledger integration - //SupportedAlgosLedger() []SigningAlgo -} - -// Signer is implemented by key stores that want to provide signing capabilities. -type Signer interface { - // Sign and SignByAddress sign byte messages with a user key. - Sign(uid string, msg []byte) ([]byte, crypto.PubKey, error) - SignByAddress(address types.Address, msg []byte) ([]byte, crypto.PubKey, error) -} - -// Importer is implemented by key stores that support import of public and private keys. -type Importer interface { - ImportPrivKey(uid, armor, passphrase string) error - ImportPubKey(uid string, armor string) error -} - -// Exporter is implemented by key stores that support export of public and private keys. -type Exporter interface { - // Export public key - ExportPubKeyArmor(uid string) (string, error) - ExportPubKeyArmorByAddress(address types.Address) (string, error) - // 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. - ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) - ExportPrivKeyArmorByAddress(address types.Address, encryptPassphrase string) (armor string, err error) -} - // keyringKeybase implements the Keybase interface by using the Keyring library // for account key persistence. type keyringKeybase struct { From ece95efe405ab2a1604c1458963abcd4424e4ccf Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 26 Mar 2020 22:37:40 +0100 Subject: [PATCH 005/148] test adding new key --- crypto/keyring/altkeyring.go | 5 ++--- crypto/keyring/altkeyring_test.go | 7 +++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index dc9ee58bc17..cfa6f200313 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -6,12 +6,12 @@ import ( "sort" "strings" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/99designs/keyring" "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/go-bip39" tmcrypto "github.com/tendermint/tendermint/crypto" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) var ( @@ -40,7 +40,6 @@ type Keyring interface { // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SigningAlgo) (Info, error) - // //// SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. //SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) // diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index b7a623f5032..582a86c1e80 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -18,4 +18,11 @@ func TestAltKeyring_List(t *testing.T) { list, err := keyring.List() require.NoError(t, err) require.Len(t, list, 0) + + _, _, err = keyring.NewMnemonic("theKey", English, Secp256k1) + require.NoError(t, err) + + list, err = keyring.List() + require.NoError(t, err) + require.Len(t, list, 1) } From cdada42a6484273a8ebe84e69c93cb0e5a371b46 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 26 Mar 2020 22:47:51 +0100 Subject: [PATCH 006/148] add test for list --- crypto/keyring/altkeyring_test.go | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 582a86c1e80..f130e87c992 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -17,12 +17,23 @@ func TestAltKeyring_List(t *testing.T) { list, err := keyring.List() require.NoError(t, err) - require.Len(t, list, 0) + require.Empty(t, list) - _, _, err = keyring.NewMnemonic("theKey", English, Secp256k1) + // Create 3 keys + uid1, uid2, uid3 := "Zkey", "Bkey", "Rkey" + _, _, err = keyring.NewMnemonic(uid1, English, Secp256k1) + require.NoError(t, err) + _, _, err = keyring.NewMnemonic(uid2, English, Secp256k1) + require.NoError(t, err) + _, _, err = keyring.NewMnemonic(uid3, English, Secp256k1) require.NoError(t, err) list, err = keyring.List() require.NoError(t, err) - require.Len(t, list, 1) + require.Len(t, list, 3) + + // Check they are in alphabetical order + require.Equal(t, uid2, list[0].GetName()) + require.Equal(t, uid3, list[1].GetName()) + require.Equal(t, uid1, list[2].GetName()) } From 760b1679573b4afed33f8cf32343a6f3453ba953 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 26 Mar 2020 23:12:00 +0100 Subject: [PATCH 007/148] implement and test Key --- crypto/keyring/altkeyring.go | 20 ++++++++++++++++++-- crypto/keyring/altkeyring_test.go | 20 ++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index cfa6f200313..1e82116511b 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -23,8 +23,9 @@ type Keyring interface { // List all keys. List() ([]Info, error) - //// Key and KeyByAddress return keys by uid and address respectively. - //Key(uid string) (Info, error) + // Key and KeyByAddress return keys by uid and address respectively. + Key(uid string) (Info, error) + //KeyByAddress(address types.Address) (Info, error) // //// Delete and DeleteByAddress remove keys. @@ -196,6 +197,21 @@ func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase stri return info, nil } +func (a altKeyring) Key(uid string) (Info, error) { + key := infoKey(uid) + + bs, err := a.db.Get(string(key)) + if err != nil { + return nil, err + } + + if len(bs.Data) == 0 { + return nil, sdkerrors.Wrap(sdkerrors.ErrKeyNotFound, uid) + } + + return unmarshalInfo(bs.Data) +} + func (a altKeyring) writeLocalKey(name string, priv tmcrypto.PrivKey, algo SigningAlgo) Info { // encrypt private key using keyring pub := priv.PubKey() diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index f130e87c992..a458748da24 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -37,3 +37,23 @@ func TestAltKeyring_List(t *testing.T) { require.Equal(t, uid3, list[1].GetName()) require.Equal(t, uid1, list[2].GetName()) } + +func TestAltKeyring_Get(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "theKey" + mnemonic, _, err := keyring.NewMnemonic(uid, English, Secp256k1) + require.NoError(t, err) + + key, err := keyring.Key(uid) + require.NoError(t, err) + require.Equal(t, key.GetName(), mnemonic.GetName()) + require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) + require.Equal(t, key.GetPubKey(), mnemonic.GetPubKey()) + require.Equal(t, key.GetAlgo(), mnemonic.GetAlgo()) + require.Equal(t, key.GetType(), mnemonic.GetType()) +} From de39a80bace03bd6630189d46f8b6d595b29b9ed Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 26 Mar 2020 23:29:27 +0100 Subject: [PATCH 008/148] create and test GetByAddress --- crypto/keyring/altkeyring.go | 20 +++++++++++++++++++- crypto/keyring/altkeyring_test.go | 20 ++++++++++++++++++++ crypto/keyring/db_keybase.go | 2 +- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 1e82116511b..5d68dbb5c62 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -25,8 +25,8 @@ type Keyring interface { // Key and KeyByAddress return keys by uid and address respectively. Key(uid string) (Info, error) + KeyByAddress(address types.Address) (Info, error) - //KeyByAddress(address types.Address) (Info, error) // //// Delete and DeleteByAddress remove keys. //Delete(uid string) error @@ -117,6 +117,24 @@ type altKeyring struct { db keyring.Keyring } +func (a altKeyring) KeyByAddress(address types.Address) (Info, error) { + ik, err := a.db.Get(string(addrKey(address))) + if err != nil { + return nil, err + } + + if len(ik.Data) == 0 { + return nil, fmt.Errorf("key with address %s not found", address) + } + + bs, err := a.db.Get(string(ik.Data)) + if err != nil { + return nil, err + } + + return unmarshalInfo(bs.Data) +} + func (a altKeyring) List() ([]Info, error) { var res []Info keys, err := a.db.Keys() diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index a458748da24..d0af28c97f7 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -51,6 +51,26 @@ func TestAltKeyring_Get(t *testing.T) { key, err := keyring.Key(uid) require.NoError(t, err) + requireEqualInfo(t, mnemonic, key) +} + +func TestAltKeyring_KeyByAddress(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "theKey" + mnemonic, _, err := keyring.NewMnemonic(uid, English, Secp256k1) + require.NoError(t, err) + + key, err := keyring.KeyByAddress(mnemonic.GetAddress()) + require.NoError(t, err) + requireEqualInfo(t, key, mnemonic) +} + +func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) require.Equal(t, key.GetPubKey(), mnemonic.GetPubKey()) diff --git a/crypto/keyring/db_keybase.go b/crypto/keyring/db_keybase.go index e1513b38e08..5e7ffe0fca3 100644 --- a/crypto/keyring/db_keybase.go +++ b/crypto/keyring/db_keybase.go @@ -417,7 +417,7 @@ func (kb dbKeybase) writeInfo(name string, info Info) { kb.db.SetSync(addrKey(info.GetAddress()), key) } -func addrKey(address types.AccAddress) []byte { +func addrKey(address types.Address) []byte { return []byte(fmt.Sprintf("%s.%s", address.String(), addressSuffix)) } From 85c4fd5c2836e3d074eb7f8be0d606f6a94e16f5 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 11:29:05 +0100 Subject: [PATCH 009/148] add delete function --- crypto/keyring/altkeyring.go | 22 ++++++++++++++++++++-- crypto/keyring/altkeyring_test.go | 23 +++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 5d68dbb5c62..a4138599a14 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -27,9 +27,8 @@ type Keyring interface { Key(uid string) (Info, error) KeyByAddress(address types.Address) (Info, error) - // //// Delete and DeleteByAddress remove keys. - //Delete(uid string) error + Delete(uid string) error //DeleteByAddress(address types.Address) error // NewMnemonic generates a new mnemonic, derives a hierarchical deterministic @@ -117,6 +116,25 @@ type altKeyring struct { db keyring.Keyring } +func (a altKeyring) Delete(uid string) error { + info, err := a.Key(uid) + if err != nil { + return err + } + + err = a.db.Remove(string(addrKey(info.GetAddress()))) + if err != nil { + return err + } + + err = a.db.Remove(string(infoKey(uid))) + if err != nil { + return err + } + + return nil +} + func (a altKeyring) KeyByAddress(address types.Address) (Info, error) { ik, err := a.db.Get(string(addrKey(address))) if err != nil { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index d0af28c97f7..1c9a7a251bb 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -70,6 +70,29 @@ func TestAltKeyring_KeyByAddress(t *testing.T) { requireEqualInfo(t, key, mnemonic) } +func TestAltKeyring_Delete(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "theKey" + _, _, err = keyring.NewMnemonic(uid, English, Secp256k1) + require.NoError(t, err) + + list, err := keyring.List() + require.NoError(t, err) + require.Len(t, list, 1) + + err = keyring.Delete(uid) + require.NoError(t, err) + + list, err = keyring.List() + require.NoError(t, err) + require.Empty(t, list) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) From 36548a77bc9922176906703f579089deb646d32a Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 11:38:20 +0100 Subject: [PATCH 010/148] add delete by address function --- crypto/keyring/altkeyring.go | 16 +++++++++++++++- crypto/keyring/altkeyring_test.go | 23 +++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index a4138599a14..4d685f4784a 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -29,7 +29,7 @@ type Keyring interface { //// Delete and DeleteByAddress remove keys. Delete(uid string) error - //DeleteByAddress(address types.Address) error + DeleteByAddress(address types.Address) error // NewMnemonic generates a new mnemonic, derives a hierarchical deterministic // key from that, and persists it to storage. Returns the generated mnemonic and the key @@ -116,6 +116,20 @@ type altKeyring struct { db keyring.Keyring } +func (a altKeyring) DeleteByAddress(address types.Address) error { + info, err := a.KeyByAddress(address) + if err != nil { + return err + } + + err = a.Delete(info.GetName()) + if err != nil { + return err + } + + return nil +} + func (a altKeyring) Delete(uid string) error { info, err := a.Key(uid) if err != nil { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 1c9a7a251bb..0f77defc743 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -93,6 +93,29 @@ func TestAltKeyring_Delete(t *testing.T) { require.Empty(t, list) } +func TestAltKeyring_DeleteByAddress(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "theKey" + mnemonic, _, err := keyring.NewMnemonic(uid, English, Secp256k1) + require.NoError(t, err) + + list, err := keyring.List() + require.NoError(t, err) + require.Len(t, list, 1) + + err = keyring.DeleteByAddress(mnemonic.GetAddress()) + require.NoError(t, err) + + list, err = keyring.List() + require.NoError(t, err) + require.Empty(t, list) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) From 57f7d5a53fed98325c1cc1b6ff4598d17bf709f0 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 12:40:36 +0100 Subject: [PATCH 011/148] add new pub key and test --- crypto/keyring/altkeyring.go | 14 ++++++++++++-- crypto/keyring/altkeyring_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 4d685f4784a..6edb56f8636 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -43,8 +43,8 @@ type Keyring interface { //// SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. //SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) // - //// SavePubKey stores a public key and returns the persisted Info structure. - //SavePubKey(uid string, pubkey crypto.PubKey, algo SigningAlgo) (Info, error) + // SavePubKey stores a public key and returns the persisted Info structure. + SavePubKey(uid string, pubkey tmcrypto.PubKey, algo SigningAlgo) (Info, error) // //// SaveMultisig stores, stores, and returns a new multsig (offline) key reference //SaveMultisig(uid string, pubkey crypto.PubKey) (Info, error) @@ -116,6 +116,10 @@ type altKeyring struct { db keyring.Keyring } +func (a altKeyring) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo SigningAlgo) (Info, error) { + return a.writeOfflineKey(uid, pubkey, algo), nil +} + func (a altKeyring) DeleteByAddress(address types.Address) error { info, err := a.KeyByAddress(address) if err != nil { @@ -293,3 +297,9 @@ func (a altKeyring) writeInfo(name string, info Info) { panic(err) } } + +func (a altKeyring) writeOfflineKey(name string, pub tmcrypto.PubKey, algo SigningAlgo) Info { + info := newOfflineInfo(name, pub, algo) + a.writeInfo(name, info) + return info +} diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 0f77defc743..9c1724ea04d 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -3,6 +3,8 @@ package keyring import ( "testing" + "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/tests" @@ -116,6 +118,31 @@ func TestAltKeyring_DeleteByAddress(t *testing.T) { require.Empty(t, list) } +func TestAltKeyring_SavePubKey(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + list, err := keyring.List() + require.NoError(t, err) + require.Empty(t, list) + + key := "offline" + priv := ed25519.GenPrivKey() + pub := priv.PubKey() + + info, err := keyring.SavePubKey(key, pub, Ed25519) + require.Nil(t, err) + require.Equal(t, pub, info.GetPubKey()) + require.Equal(t, key, info.GetName()) + + list, err = keyring.List() + require.NoError(t, err) + require.Equal(t, 1, len(list)) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) From 2d22fbdfcd8b43a6ee6ebcdc22ba98b2d0e74ccf Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 13:43:59 +0100 Subject: [PATCH 012/148] create function for writing multisign --- client/keys/add.go | 3 +- crypto/keyring/altkeyring.go | 57 ++++++++++++++++++++++++------------ 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/client/keys/add.go b/client/keys/add.go index d8f768cc4f1..80f3bb243cb 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -117,9 +117,10 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keybase, inBuf *buf showMnemonic := !viper.GetBool(flagNoBackup) algo := keyring.SigningAlgo(viper.GetString(flagKeyAlgo)) - if algo == keyring.SigningAlgo("") { + if algo == "" { algo = keyring.Secp256k1 } + if !keyring.IsSupportedAlgorithm(kb.SupportedAlgos(), algo) { return keyring.ErrUnsupportedSigningAlgo } diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 6edb56f8636..efcd02cc155 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -42,12 +42,12 @@ type Keyring interface { //// SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. //SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) - // + // SavePubKey stores a public key and returns the persisted Info structure. SavePubKey(uid string, pubkey tmcrypto.PubKey, algo SigningAlgo) (Info, error) - // - //// SaveMultisig stores, stores, and returns a new multsig (offline) key reference - //SaveMultisig(uid string, pubkey crypto.PubKey) (Info, error) + + // SaveMultisig stores, stores, and returns a new multsig (offline) key reference + SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) // //// SupportedAlgos returns a list of signing algorithms supported by the keybase //SupportedAlgos() []SigningAlgo @@ -116,8 +116,12 @@ type altKeyring struct { db keyring.Keyring } +func (a altKeyring) SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) { + return a.writeMultisigKey(uid, pubkey) +} + func (a altKeyring) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo SigningAlgo) (Info, error) { - return a.writeOfflineKey(uid, pubkey, algo), nil + return a.writeOfflineKey(uid, pubkey, algo) } func (a altKeyring) DeleteByAddress(address types.Address) error { @@ -244,11 +248,7 @@ func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase stri return nil, err } - var info Info - - info = a.writeLocalKey(uid, privKey, algo) - - return info, nil + return a.writeLocalKey(uid, privKey, algo) } func (a altKeyring) Key(uid string) (Info, error) { @@ -266,17 +266,20 @@ func (a altKeyring) Key(uid string) (Info, error) { return unmarshalInfo(bs.Data) } -func (a altKeyring) writeLocalKey(name string, priv tmcrypto.PrivKey, algo SigningAlgo) Info { +func (a altKeyring) writeLocalKey(name string, priv tmcrypto.PrivKey, algo SigningAlgo) (Info, error) { // encrypt private key using keyring pub := priv.PubKey() info := newLocalInfo(name, pub, string(priv.Bytes()), algo) - a.writeInfo(name, info) + err := a.writeInfo(name, info) + if err != nil { + return nil, err + } - return info + return info, nil } -func (a altKeyring) writeInfo(name string, info Info) { +func (a altKeyring) writeInfo(name string, info Info) error { // write the info by key key := infoKey(name) serializedInfo := marshalInfo(info) @@ -286,7 +289,7 @@ func (a altKeyring) writeInfo(name string, info Info) { Data: serializedInfo, }) if err != nil { - panic(err) + return err } err = a.db.Set(keyring.Item{ @@ -294,12 +297,28 @@ func (a altKeyring) writeInfo(name string, info Info) { Data: key, }) if err != nil { - panic(err) + return err } + + return nil } -func (a altKeyring) writeOfflineKey(name string, pub tmcrypto.PubKey, algo SigningAlgo) Info { +func (a altKeyring) writeOfflineKey(name string, pub tmcrypto.PubKey, algo SigningAlgo) (Info, error) { info := newOfflineInfo(name, pub, algo) - a.writeInfo(name, info) - return info + err := a.writeInfo(name, info) + if err != nil { + return nil, err + } + + return info, nil +} + +func (a altKeyring) writeMultisigKey(name string, pub tmcrypto.PubKey) (Info, error) { + info := NewMultiInfo(name, pub) + err := a.writeInfo(name, info) + if err != nil { + return nil, err + } + + return info, nil } From a9aab77d47292142e334007d078320303404ae8d Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 14:38:40 +0100 Subject: [PATCH 013/148] use addrKeyByString --- crypto/keyring/altkeyring.go | 6 +++--- crypto/keyring/db_keybase.go | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index efcd02cc155..42dfd28814f 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -144,7 +144,7 @@ func (a altKeyring) Delete(uid string) error { return err } - err = a.db.Remove(string(addrKey(info.GetAddress()))) + err = a.db.Remove(addrKeyAsString(info.GetAddress())) if err != nil { return err } @@ -158,7 +158,7 @@ func (a altKeyring) Delete(uid string) error { } func (a altKeyring) KeyByAddress(address types.Address) (Info, error) { - ik, err := a.db.Get(string(addrKey(address))) + ik, err := a.db.Get(addrKeyAsString(address)) if err != nil { return nil, err } @@ -293,7 +293,7 @@ func (a altKeyring) writeInfo(name string, info Info) error { } err = a.db.Set(keyring.Item{ - Key: string(addrKey(info.GetAddress())), + Key: addrKeyAsString(info.GetAddress()), Data: key, }) if err != nil { diff --git a/crypto/keyring/db_keybase.go b/crypto/keyring/db_keybase.go index 5e7ffe0fca3..7bb58516f75 100644 --- a/crypto/keyring/db_keybase.go +++ b/crypto/keyring/db_keybase.go @@ -421,6 +421,10 @@ func addrKey(address types.Address) []byte { return []byte(fmt.Sprintf("%s.%s", address.String(), addressSuffix)) } +func addrKeyAsString(address types.Address) string { + return fmt.Sprintf("%s.%s", address.String(), addressSuffix) +} + func infoKey(name string) []byte { return []byte(fmt.Sprintf("%s.%s", name, infoSuffix)) } From 63fbdf3905ef461bc5c7c2fcb1571a420fec290d Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 14:59:54 +0100 Subject: [PATCH 014/148] implement and test multisig --- crypto/keyring/altkeyring.go | 1 + crypto/keyring/altkeyring_test.go | 31 ++++++++++++++++++++++++++++++- crypto/keyring/db_keybase.go | 2 +- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 42dfd28814f..f3347d687e5 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -48,6 +48,7 @@ type Keyring interface { // SaveMultisig stores, stores, and returns a new multsig (offline) key reference SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) + // //// SupportedAlgos returns a list of signing algorithms supported by the keybase //SupportedAlgos() []SigningAlgo diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 9c1724ea04d..d863aad85de 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -3,6 +3,10 @@ package keyring import ( "testing" + "github.com/tendermint/tendermint/crypto" + + "github.com/tendermint/tendermint/crypto/multisig" + "github.com/tendermint/tendermint/crypto/ed25519" "github.com/stretchr/testify/require" @@ -133,7 +137,7 @@ func TestAltKeyring_SavePubKey(t *testing.T) { priv := ed25519.GenPrivKey() pub := priv.PubKey() - info, err := keyring.SavePubKey(key, pub, Ed25519) + info, err := keyring.SavePubKey(key, pub, Secp256k1) require.Nil(t, err) require.Equal(t, pub, info.GetPubKey()) require.Equal(t, key, info.GetName()) @@ -143,6 +147,31 @@ func TestAltKeyring_SavePubKey(t *testing.T) { require.Equal(t, 1, len(list)) } +func TestAltKeyring_SaveMultisig(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + mnemonic1, _, err := keyring.NewMnemonic("key1", English, Secp256k1) + require.NoError(t, err) + mnemonic2, _, err := keyring.NewMnemonic("key2", English, Secp256k1) + require.NoError(t, err) + + key := "multi" + pub := multisig.NewPubKeyMultisigThreshold(2, []crypto.PubKey{mnemonic1.GetPubKey(), mnemonic2.GetPubKey()}) + + info, err := keyring.SaveMultisig(key, pub) + require.Nil(t, err) + require.Equal(t, pub, info.GetPubKey()) + require.Equal(t, key, info.GetName()) + + list, err := keyring.List() + require.NoError(t, err) + require.Len(t, list, 3) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) diff --git a/crypto/keyring/db_keybase.go b/crypto/keyring/db_keybase.go index 7bb58516f75..f7c67e561a9 100644 --- a/crypto/keyring/db_keybase.go +++ b/crypto/keyring/db_keybase.go @@ -418,7 +418,7 @@ func (kb dbKeybase) writeInfo(name string, info Info) { } func addrKey(address types.Address) []byte { - return []byte(fmt.Sprintf("%s.%s", address.String(), addressSuffix)) + return []byte(addrKeyAsString(address)) } func addrKeyAsString(address types.Address) string { From 7255a32d56d79e060ae42332166537b4ba76fb36 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 16:29:04 +0100 Subject: [PATCH 015/148] add test for unsupported signing algo --- crypto/keyring/altkeyring.go | 25 ++++++++++++++++++------- crypto/keyring/altkeyring_test.go | 4 ++++ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index f3347d687e5..874577cf38a 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -49,7 +49,6 @@ type Keyring interface { // SaveMultisig stores, stores, and returns a new multsig (offline) key reference SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) - // //// SupportedAlgos returns a list of signing algorithms supported by the keybase //SupportedAlgos() []SigningAlgo // @@ -85,7 +84,7 @@ type Exporter interface { // options can be applied when generating this new Keybase. // Available backends are "os", "file", "kwallet", "pass", "test". func NewAltKeyring( - appName, backend, rootDir string, userInput io.Reader, opts ...KeybaseOption, + appName, backend, rootDir string, userInput io.Reader, ) (Keyring, error) { var db keyring.Keyring @@ -110,11 +109,23 @@ func NewAltKeyring( return nil, err } - return altKeyring{db: db}, nil + return altKeyring{ + db: db, + options: altKrOptions{ + supportedAlgos: []SigningAlgo{Secp256k1}, + supportedAlgosLedger: []SigningAlgo{Secp256k1}, + }, + }, nil } type altKeyring struct { - db keyring.Keyring + db keyring.Keyring + options altKrOptions +} + +type altKrOptions struct { + supportedAlgos []SigningAlgo + supportedAlgosLedger []SigningAlgo } func (a altKeyring) SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) { @@ -213,9 +224,9 @@ func (a altKeyring) NewMnemonic(uid string, language Language, algo SigningAlgo) return nil, "", ErrUnsupportedLanguage } - //if !IsSupportedAlgorithm(a.SupportedAlgos(), algo) { - // return nil, "", ErrUnsupportedSigningAlgo - //} + if !IsSupportedAlgorithm(a.options.supportedAlgos, algo) { + return nil, "", ErrUnsupportedSigningAlgo + } // Default number of words (24): This generates a mnemonic directly from the // number of words by reading system entropy. diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index d863aad85de..816160d1e58 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -25,6 +25,10 @@ func TestAltKeyring_List(t *testing.T) { require.NoError(t, err) require.Empty(t, list) + // Fails on creating unsupported SigningAlgo + _, _, err = keyring.NewMnemonic("failing", English, Ed25519) + require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) + // Create 3 keys uid1, uid2, uid3 := "Zkey", "Bkey", "Rkey" _, _, err = keyring.NewMnemonic(uid1, English, Secp256k1) From f3e06241fadcb08cfb219dc5d6d3a9b7d93ab0c4 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 18:16:35 +0100 Subject: [PATCH 016/148] refactor algorithm --- crypto/keyring/alt_signing_algorithms.go | 29 ++++++++++++++++ crypto/keyring/alt_signing_algorithms_test.go | 20 +++++++++++ crypto/keyring/altkeyring.go | 34 +++++++++---------- crypto/keyring/altkeyring_test.go | 32 +++++++++-------- crypto/keyring/base_keybase.go | 1 - 5 files changed, 82 insertions(+), 34 deletions(-) create mode 100644 crypto/keyring/alt_signing_algorithms.go create mode 100644 crypto/keyring/alt_signing_algorithms_test.go diff --git a/crypto/keyring/alt_signing_algorithms.go b/crypto/keyring/alt_signing_algorithms.go new file mode 100644 index 00000000000..9c7d22072c6 --- /dev/null +++ b/crypto/keyring/alt_signing_algorithms.go @@ -0,0 +1,29 @@ +package keyring + +import "github.com/tendermint/tendermint/crypto" + +type AltSigningAlgo struct { + Name SigningAlgo + DeriveKey AltDeriveKeyFunc + PrivKeyGen AltPrivKeyGenFunc +} + +type AltDeriveKeyFunc func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) +type AltPrivKeyGenFunc func(bz []byte) crypto.PrivKey + +var ( + // Secp256k1 uses the Bitcoin secp256k1 ECDSA parameters. + AltSecp256k1 = AltSigningAlgo{Name: Secp256k1, DeriveKey: SecpDeriveKey, PrivKeyGen: SecpPrivKeyGen} +) + +type AltSigningAlgoList []AltSigningAlgo + +func (l AltSigningAlgoList) Contains(algo AltSigningAlgo) bool { + for _, cAlgo := range l { + if cAlgo.Name == algo.Name { + return true + } + } + + return false +} diff --git a/crypto/keyring/alt_signing_algorithms_test.go b/crypto/keyring/alt_signing_algorithms_test.go new file mode 100644 index 00000000000..91c2e96cf67 --- /dev/null +++ b/crypto/keyring/alt_signing_algorithms_test.go @@ -0,0 +1,20 @@ +package keyring + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAltSigningAlgoList_Contains(t *testing.T) { + list := AltSigningAlgoList{ + AltSecp256k1, + } + + notSupportedAlgo := AltSigningAlgo{ + Name: "anotherAlgo", + DeriveKey: nil, + } + assert.True(t, list.Contains(AltSecp256k1)) + assert.False(t, list.Contains(notSupportedAlgo)) +} diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 874577cf38a..c354ecaf508 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -35,10 +35,10 @@ type Keyring interface { // key from that, and persists it to storage. Returns the generated mnemonic and the key // Info. It returns an error if it fails to generate a key for the given algo type, or if // another key is already stored under the same name. - NewMnemonic(uid string, language Language, algo SigningAlgo) (Info, string, error) + NewMnemonic(uid string, language Language, algo AltSigningAlgo) (Info, string, error) // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. - NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SigningAlgo) (Info, error) + NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo AltSigningAlgo) (Info, error) //// SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. //SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) @@ -49,9 +49,6 @@ type Keyring interface { // SaveMultisig stores, stores, and returns a new multsig (offline) key reference SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) - //// SupportedAlgos returns a list of signing algorithms supported by the keybase - //SupportedAlgos() []SigningAlgo - // //// SupportedAlgosLedger returns a list of signing algorithms supported by the keybase's ledger integration //SupportedAlgosLedger() []SigningAlgo } @@ -112,8 +109,8 @@ func NewAltKeyring( return altKeyring{ db: db, options: altKrOptions{ - supportedAlgos: []SigningAlgo{Secp256k1}, - supportedAlgosLedger: []SigningAlgo{Secp256k1}, + supportedAlgos: []AltSigningAlgo{AltSecp256k1}, + supportedAlgosLedger: []AltSigningAlgo{AltSecp256k1}, }, }, nil } @@ -124,8 +121,8 @@ type altKeyring struct { } type altKrOptions struct { - supportedAlgos []SigningAlgo - supportedAlgosLedger []SigningAlgo + supportedAlgos AltSigningAlgoList + supportedAlgosLedger AltSigningAlgoList } func (a altKeyring) SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) { @@ -219,12 +216,12 @@ func (a altKeyring) List() ([]Info, error) { return res, nil } -func (a altKeyring) NewMnemonic(uid string, language Language, algo SigningAlgo) (Info, string, error) { +func (a altKeyring) NewMnemonic(uid string, language Language, algo AltSigningAlgo) (Info, string, error) { if language != English { return nil, "", ErrUnsupportedLanguage } - if !IsSupportedAlgorithm(a.options.supportedAlgos, algo) { + if !a.options.supportedAlgos.Contains(algo) { return nil, "", ErrUnsupportedSigningAlgo } @@ -248,19 +245,20 @@ func (a altKeyring) NewMnemonic(uid string, language Language, algo SigningAlgo) return info, mnemonic, err } -func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase string, hdPath string, algo SigningAlgo) (Info, error) { +func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase string, hdPath string, algo AltSigningAlgo) (Info, error) { + //if !IsSupportedAlgorithm(a.options.supportedAlgos, algo) { + // return nil, ErrUnsupportedSigningAlgo + //} + // // create master key and derive first key for keyring - derivedPriv, err := StdDeriveKey(mnemonic, bip39Passphrase, hdPath, algo) + derivedPriv, err := algo.DeriveKey(mnemonic, bip39Passphrase, hdPath) if err != nil { return nil, err } - privKey, err := StdPrivKeyGen(derivedPriv, algo) - if err != nil { - return nil, err - } + privKey := algo.PrivKeyGen(derivedPriv) - return a.writeLocalKey(uid, privKey, algo) + return a.writeLocalKey(uid, privKey, SigningAlgo(algo.Name)) } func (a altKeyring) Key(uid string) (Info, error) { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 816160d1e58..ccd019de361 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -3,17 +3,19 @@ package keyring import ( "testing" + "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" - - "github.com/tendermint/tendermint/crypto/multisig" - "github.com/tendermint/tendermint/crypto/ed25519" - - "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto/multisig" "github.com/cosmos/cosmos-sdk/tests" ) +var unsupportedAlgo = AltSigningAlgo{ + Name: "unsupported", + DeriveKey: nil, +} + func TestAltKeyring_List(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) @@ -26,16 +28,16 @@ func TestAltKeyring_List(t *testing.T) { require.Empty(t, list) // Fails on creating unsupported SigningAlgo - _, _, err = keyring.NewMnemonic("failing", English, Ed25519) + _, _, err = keyring.NewMnemonic("failing", English, unsupportedAlgo) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) // Create 3 keys uid1, uid2, uid3 := "Zkey", "Bkey", "Rkey" - _, _, err = keyring.NewMnemonic(uid1, English, Secp256k1) + _, _, err = keyring.NewMnemonic(uid1, English, AltSecp256k1) require.NoError(t, err) - _, _, err = keyring.NewMnemonic(uid2, English, Secp256k1) + _, _, err = keyring.NewMnemonic(uid2, English, AltSecp256k1) require.NoError(t, err) - _, _, err = keyring.NewMnemonic(uid3, English, Secp256k1) + _, _, err = keyring.NewMnemonic(uid3, English, AltSecp256k1) require.NoError(t, err) list, err = keyring.List() @@ -56,7 +58,7 @@ func TestAltKeyring_Get(t *testing.T) { require.NoError(t, err) uid := "theKey" - mnemonic, _, err := keyring.NewMnemonic(uid, English, Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) key, err := keyring.Key(uid) @@ -72,7 +74,7 @@ func TestAltKeyring_KeyByAddress(t *testing.T) { require.NoError(t, err) uid := "theKey" - mnemonic, _, err := keyring.NewMnemonic(uid, English, Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) key, err := keyring.KeyByAddress(mnemonic.GetAddress()) @@ -88,7 +90,7 @@ func TestAltKeyring_Delete(t *testing.T) { require.NoError(t, err) uid := "theKey" - _, _, err = keyring.NewMnemonic(uid, English, Secp256k1) + _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) list, err := keyring.List() @@ -111,7 +113,7 @@ func TestAltKeyring_DeleteByAddress(t *testing.T) { require.NoError(t, err) uid := "theKey" - mnemonic, _, err := keyring.NewMnemonic(uid, English, Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) list, err := keyring.List() @@ -158,9 +160,9 @@ func TestAltKeyring_SaveMultisig(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - mnemonic1, _, err := keyring.NewMnemonic("key1", English, Secp256k1) + mnemonic1, _, err := keyring.NewMnemonic("key1", English, AltSecp256k1) require.NoError(t, err) - mnemonic2, _, err := keyring.NewMnemonic("key2", English, Secp256k1) + mnemonic2, _, err := keyring.NewMnemonic("key2", English, AltSecp256k1) require.NoError(t, err) key := "multi" diff --git a/crypto/keyring/base_keybase.go b/crypto/keyring/base_keybase.go index c2f7952b820..3316da181e2 100644 --- a/crypto/keyring/base_keybase.go +++ b/crypto/keyring/base_keybase.go @@ -70,7 +70,6 @@ func SecpPrivKeyGen(bz []byte) tmcrypto.PrivKey { func (kb baseKeybase) CreateAccount( keyWriter keyWriter, name, mnemonic, bip39Passphrase, encryptPasswd, hdPath string, algo SigningAlgo, ) (Info, error) { - // create master key and derive first key for keyring derivedPriv, err := kb.options.deriveFunc(mnemonic, bip39Passphrase, hdPath, algo) if err != nil { From 0edc2d8009b66e55745a2fa924948eed02c14291 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 18:39:21 +0100 Subject: [PATCH 017/148] supported algorithm changed --- crypto/keyring/altkeyring.go | 14 +++++++++----- crypto/keyring/altkeyring_test.go | 32 +++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index c354ecaf508..1fd06bf60e4 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -221,7 +221,7 @@ func (a altKeyring) NewMnemonic(uid string, language Language, algo AltSigningAl return nil, "", ErrUnsupportedLanguage } - if !a.options.supportedAlgos.Contains(algo) { + if !a.isSupportedSigningAlgo(algo) { return nil, "", ErrUnsupportedSigningAlgo } @@ -246,10 +246,10 @@ func (a altKeyring) NewMnemonic(uid string, language Language, algo AltSigningAl } func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase string, hdPath string, algo AltSigningAlgo) (Info, error) { - //if !IsSupportedAlgorithm(a.options.supportedAlgos, algo) { - // return nil, ErrUnsupportedSigningAlgo - //} - // + if !a.isSupportedSigningAlgo(algo) { + return nil, ErrUnsupportedSigningAlgo + } + // create master key and derive first key for keyring derivedPriv, err := algo.DeriveKey(mnemonic, bip39Passphrase, hdPath) if err != nil { @@ -261,6 +261,10 @@ func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase stri return a.writeLocalKey(uid, privKey, SigningAlgo(algo.Name)) } +func (a altKeyring) isSupportedSigningAlgo(algo AltSigningAlgo) bool { + return a.options.supportedAlgos.Contains(algo) +} + func (a altKeyring) Key(uid string) (Info, error) { key := infoKey(uid) diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index ccd019de361..d20211cee23 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -3,6 +3,9 @@ package keyring import ( "testing" + "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/go-bip39" + "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" @@ -50,6 +53,35 @@ func TestAltKeyring_List(t *testing.T) { require.Equal(t, uid1, list[2].GetName()) } +func TestAltKeyring_NewAccount(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + entropy, err := bip39.NewEntropy(defaultEntropySize) + require.NoError(t, err) + + mnemonic, err := bip39.NewMnemonic(entropy) + require.NoError(t, err) + + theUid := "newUid" + + // Fails on creating unsupported SigningAlgo + info, err := keyring.NewAccount(theUid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), unsupportedAlgo) + require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) + + info, err = keyring.NewAccount(theUid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), AltSecp256k1) + require.NoError(t, err) + + require.Equal(t, theUid, info.GetName()) + + list, err := keyring.List() + require.NoError(t, err) + require.Len(t, list, 1) +} + func TestAltKeyring_Get(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) From 758af071779463b1d463c0a36352f2b37952dde8 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 19:22:15 +0100 Subject: [PATCH 018/148] update al keyring --- crypto/keyring/altkeyring.go | 6 +++--- crypto/keyring/altkeyring_test.go | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 1fd06bf60e4..d80292e103d 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -44,7 +44,7 @@ type Keyring interface { //SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) // SavePubKey stores a public key and returns the persisted Info structure. - SavePubKey(uid string, pubkey tmcrypto.PubKey, algo SigningAlgo) (Info, error) + SavePubKey(uid string, pubkey tmcrypto.PubKey, algo AltSigningAlgo) (Info, error) // SaveMultisig stores, stores, and returns a new multsig (offline) key reference SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) @@ -129,8 +129,8 @@ func (a altKeyring) SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, erro return a.writeMultisigKey(uid, pubkey) } -func (a altKeyring) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo SigningAlgo) (Info, error) { - return a.writeOfflineKey(uid, pubkey, algo) +func (a altKeyring) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo AltSigningAlgo) (Info, error) { + return a.writeOfflineKey(uid, pubkey, algo.Name) } func (a altKeyring) DeleteByAddress(address types.Address) error { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index d20211cee23..1dbdbae7466 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -3,15 +3,14 @@ package keyring import ( "testing" - "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/go-bip39" - "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/multisig" "github.com/cosmos/cosmos-sdk/tests" + "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/go-bip39" ) var unsupportedAlgo = AltSigningAlgo{ @@ -175,10 +174,11 @@ func TestAltKeyring_SavePubKey(t *testing.T) { priv := ed25519.GenPrivKey() pub := priv.PubKey() - info, err := keyring.SavePubKey(key, pub, Secp256k1) + info, err := keyring.SavePubKey(key, pub, AltSecp256k1) require.Nil(t, err) require.Equal(t, pub, info.GetPubKey()) require.Equal(t, key, info.GetName()) + require.Equal(t, AltSecp256k1.Name, info.GetAlgo()) list, err = keyring.List() require.NoError(t, err) From a990c74d45c804adc1b1919b69019daacf626b02 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 19:23:18 +0100 Subject: [PATCH 019/148] update options --- crypto/keyring/altkeyring.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index d80292e103d..4dbb5ceebfa 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -109,8 +109,8 @@ func NewAltKeyring( return altKeyring{ db: db, options: altKrOptions{ - supportedAlgos: []AltSigningAlgo{AltSecp256k1}, - supportedAlgosLedger: []AltSigningAlgo{AltSecp256k1}, + supportedAlgos: AltSigningAlgoList{AltSecp256k1}, + supportedAlgosLedger: AltSigningAlgoList{AltSecp256k1}, }, }, nil } From d999ad100f876d01e0befd47b4c79e5b846a9118 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 21:02:47 +0100 Subject: [PATCH 020/148] add supported algorithm test and SAveLedgerKey --- crypto/keyring/altkeyring.go | 36 ++++++++++++++++++++++++++----- crypto/keyring/altkeyring_test.go | 20 +++++++++++++++++ 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 4dbb5ceebfa..fae9622895d 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -6,6 +6,9 @@ import ( "sort" "strings" + "github.com/cosmos/cosmos-sdk/crypto" + "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/99designs/keyring" "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/go-bip39" @@ -40,17 +43,14 @@ type Keyring interface { // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo AltSigningAlgo) (Info, error) - //// SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. - //SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) + // SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. + SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, account, index uint32) (Info, error) // SavePubKey stores a public key and returns the persisted Info structure. SavePubKey(uid string, pubkey tmcrypto.PubKey, algo AltSigningAlgo) (Info, error) // SaveMultisig stores, stores, and returns a new multsig (offline) key reference SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) - - //// SupportedAlgosLedger returns a list of signing algorithms supported by the keybase's ledger integration - //SupportedAlgosLedger() []SigningAlgo } // Signer is implemented by key stores that want to provide signing capabilities. @@ -120,6 +120,32 @@ type altKeyring struct { options altKrOptions } +func (a altKeyring) SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, account, index uint32) (Info, error) { + if !a.options.supportedAlgosLedger.Contains(algo) { + return nil, ErrUnsupportedSigningAlgo + } + + coinType := types.GetConfig().GetCoinType() + hdPath := hd.NewFundraiserParams(account, coinType, index) + + priv, _, err := crypto.NewPrivKeyLedgerSecp256k1(*hdPath, hrp) + if err != nil { + return nil, err + } + + return a.writeLedgerKey(uid, priv.PubKey(), *hdPath, algo.Name) +} + +func (a altKeyring) writeLedgerKey(name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo SigningAlgo) (Info, error) { + info := newLedgerInfo(name, pub, path, algo) + err := a.writeInfo(name, info) + if err != nil { + return nil, err + } + + return info, nil +} + type altKrOptions struct { supportedAlgos AltSigningAlgoList supportedAlgosLedger AltSigningAlgoList diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 1dbdbae7466..dea971bf8a1 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -81,6 +81,26 @@ func TestAltKeyring_NewAccount(t *testing.T) { require.Len(t, list, 1) } +func TestAltKeyring_SaveLedgerKey(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + // Test unsupported Algo + i1, err := keyring.SaveLedgerKey("key", unsupportedAlgo, "cosmos", 0, 0) + require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) + + i1, err = keyring.SaveLedgerKey("key", AltSecp256k1, "cosmos", 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()) +} + func TestAltKeyring_Get(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) From 04b03a77b35118224f0d47c2875899a1bdb3211d Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 21:05:03 +0100 Subject: [PATCH 021/148] fix imports --- crypto/keyring/altkeyring.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index fae9622895d..a9f5cf2ef43 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -6,15 +6,14 @@ import ( "sort" "strings" + "github.com/99designs/keyring" + "github.com/cosmos/cosmos-sdk/crypto" "github.com/cosmos/cosmos-sdk/crypto/keys/hd" - - "github.com/99designs/keyring" "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/go-bip39" tmcrypto "github.com/tendermint/tendermint/crypto" - - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) var ( From 1c736f1cbbf39eeb5196b6043ffca166a668ff77 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 30 Mar 2020 12:59:21 +0200 Subject: [PATCH 022/148] add signature into keyring --- crypto/keyring/altkeyring.go | 47 ++++++++++++++++++++++++++++++- crypto/keyring/altkeyring_test.go | 19 +++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index a9f5cf2ef43..3c2bbbcbce5 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -6,6 +6,9 @@ import ( "sort" "strings" + "github.com/pkg/errors" + cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" + "github.com/99designs/keyring" "github.com/cosmos/cosmos-sdk/crypto" @@ -50,12 +53,16 @@ type Keyring interface { // SaveMultisig stores, stores, and returns a new multsig (offline) key reference SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) + + Signer } // Signer is implemented by key stores that want to provide signing capabilities. type Signer interface { - // Sign and SignByAddress sign byte messages with a user key. + // Sign sign byte messages with a user key. Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error) + + // SignByAddress sign byte messages with a user key providing the address. SignByAddress(address types.Address, msg []byte) ([]byte, tmcrypto.PubKey, error) } @@ -119,6 +126,44 @@ type altKeyring struct { options altKrOptions } +func (a altKeyring) Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error) { + info, err := a.Key(uid) + if err != nil { + return nil, nil, err + } + + var priv tmcrypto.PrivKey + + switch i := info.(type) { + case localInfo: + if i.PrivKeyArmor == "" { + return nil, nil, fmt.Errorf("private key not available") + } + + priv, err = cryptoAmino.PrivKeyFromBytes([]byte(i.PrivKeyArmor)) + if err != nil { + return nil, nil, err + } + + case ledgerInfo: + return SignWithLedger(info, msg) + + case offlineInfo, multiInfo: + return nil, info.GetPubKey(), 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 (a altKeyring) SignByAddress(address types.Address, msg []byte) ([]byte, tmcrypto.PubKey, error) { + panic("implement me") +} + func (a altKeyring) SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, account, index uint32) (Info, error) { if !a.options.supportedAlgosLedger.Contains(algo) { return nil, ErrUnsupportedSigningAlgo diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index dea971bf8a1..2b2d3f5f40e 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -230,6 +230,25 @@ func TestAltKeyring_SaveMultisig(t *testing.T) { require.Len(t, list, 3) } +func TestAltKeyring_Sign(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "jack" + _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) + require.NoError(t, err) + + msg := []byte("some message") + + sign, key, err := keyring.Sign(uid, msg) + require.NoError(t, err) + + require.True(t, key.VerifyBytes(msg, sign)) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) From 9ede030989c69abb96b874f8d3aeabd72816d58b Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 30 Mar 2020 13:07:47 +0200 Subject: [PATCH 023/148] add method to sign by address --- crypto/keyring/altkeyring.go | 7 ++++++- crypto/keyring/altkeyring_test.go | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 3c2bbbcbce5..9de2d91c377 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -161,7 +161,12 @@ func (a altKeyring) Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error } func (a altKeyring) SignByAddress(address types.Address, msg []byte) ([]byte, tmcrypto.PubKey, error) { - panic("implement me") + key, err := a.KeyByAddress(address) + if err != nil { + return nil, nil, err + } + + return a.Sign(key.GetName(), msg) } func (a altKeyring) SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, account, index uint32) (Info, error) { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 2b2d3f5f40e..90f31dcc4c5 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -249,6 +249,25 @@ func TestAltKeyring_Sign(t *testing.T) { require.True(t, key.VerifyBytes(msg, sign)) } +func TestAltKeyring_SignByAddress(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "jack" + mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) + require.NoError(t, err) + + msg := []byte("some message") + + sign, key, err := keyring.SignByAddress(mnemonic.GetAddress(), msg) + require.NoError(t, err) + + require.True(t, key.VerifyBytes(msg, sign)) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) From 869b35ae239fb8b437eee2749a8ae22b04afa6fc Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 30 Mar 2020 16:23:45 +0200 Subject: [PATCH 024/148] implement import export --- crypto/keyring/altkeyring.go | 92 ++++++++++++++++++++++++++++++- crypto/keyring/altkeyring_test.go | 31 +++++++++++ 2 files changed, 120 insertions(+), 3 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 9de2d91c377..c2a39f033c1 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -6,10 +6,11 @@ import ( "sort" "strings" - "github.com/pkg/errors" - cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" + "github.com/cosmos/cosmos-sdk/crypto/keys/mintkey" "github.com/99designs/keyring" + "github.com/pkg/errors" + cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" "github.com/cosmos/cosmos-sdk/crypto" "github.com/cosmos/cosmos-sdk/crypto/keys/hd" @@ -55,6 +56,9 @@ type Keyring interface { SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) Signer + + Importer + Exporter } // Signer is implemented by key stores that want to provide signing capabilities. @@ -126,6 +130,88 @@ type altKeyring struct { options altKrOptions } +func (a altKeyring) ExportPubKeyArmor(uid string) (string, error) { + panic("implement me") +} + +func (a altKeyring) ExportPubKeyArmorByAddress(address types.Address) (string, error) { + panic("implement me") +} + +func (a altKeyring) ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) { + priv, err := a.ExportPrivateKeyObject(uid) + if err != nil { + return "", err + } + + info, err := a.Key(uid) + if err != nil { + return "", err + } + + return mintkey.EncryptArmorPrivKey(priv, encryptPassphrase, string(info.GetAlgo())), nil +} + +// ExportPrivateKeyObject exports an armored private key object. +func (a altKeyring) ExportPrivateKeyObject(uid string) (tmcrypto.PrivKey, error) { + info, err := a.Key(uid) + if err != nil { + return nil, err + } + + var priv tmcrypto.PrivKey + + switch linfo := info.(type) { + case localInfo: + if linfo.PrivKeyArmor == "" { + err = fmt.Errorf("private key not available") + return nil, err + } + + priv, err = cryptoAmino.PrivKeyFromBytes([]byte(linfo.PrivKeyArmor)) + if err != nil { + return nil, err + } + + case ledgerInfo, offlineInfo, multiInfo: + return nil, errors.New("only works on local private keys") + } + + return priv, nil +} + +func (a altKeyring) ExportPrivKeyArmorByAddress(address types.Address, encryptPassphrase string) (armor string, err error) { + panic("implement me") +} + +func (a altKeyring) ImportPrivKey(uid, armor, passphrase string) error { + if a.hasKey(uid) { + return fmt.Errorf("cannot overwrite key: %s", uid) + } + + privKey, algo, err := mintkey.UnarmorDecryptPrivKey(armor, passphrase) + if err != nil { + return errors.Wrap(err, "failed to decrypt private key") + } + + _, err = a.writeLocalKey(uid, privKey, SigningAlgo(algo)) + if err != nil { + return err + } + + return nil +} + +// HasKey returns whether the key exists in the keyring. +func (a altKeyring) hasKey(name string) bool { + bz, _ := a.Key(name) + return bz != nil +} + +func (a altKeyring) ImportPubKey(uid string, armor string) error { + panic("implement me") +} + func (a altKeyring) Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error) { info, err := a.Key(uid) if err != nil { @@ -333,7 +419,7 @@ func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase stri privKey := algo.PrivKeyGen(derivedPriv) - return a.writeLocalKey(uid, privKey, SigningAlgo(algo.Name)) + return a.writeLocalKey(uid, privKey, algo.Name) } func (a altKeyring) isSupportedSigningAlgo(algo AltSigningAlgo) bool { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 90f31dcc4c5..afbfae139fb 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -1,8 +1,11 @@ package keyring import ( + "fmt" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" @@ -268,6 +271,34 @@ func TestAltKeyring_SignByAddress(t *testing.T) { require.True(t, key.VerifyBytes(msg, sign)) } +func TestAltKeyring_ImportExportPrivKey(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "theId" + _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) + require.NoError(t, err) + + passphrase := "somePass" + armor, err := keyring.ExportPrivKeyArmor(uid, passphrase) + require.NoError(t, err) + + // Should fail importing private key on existing key. + err = keyring.ImportPrivKey(uid, armor, passphrase) + require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", uid)) + + newUid := "theNewId" + // Should fail importing with wrong password + err = keyring.ImportPrivKey(newUid, armor, "wrongPass") + require.EqualError(t, err, "failed to decrypt private key: ciphertext decryption failed") + + err = keyring.ImportPrivKey(newUid, armor, passphrase) + assert.NoError(t, err) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) From 67c4942a4fd723282fe96b2fefdeb9527405c114 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 30 Mar 2020 16:32:28 +0200 Subject: [PATCH 025/148] implement the alt keyring --- crypto/keyring/altkeyring.go | 7 ++++++- crypto/keyring/altkeyring_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index c2a39f033c1..e9ed4da4800 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -181,7 +181,12 @@ func (a altKeyring) ExportPrivateKeyObject(uid string) (tmcrypto.PrivKey, error) } func (a altKeyring) ExportPrivKeyArmorByAddress(address types.Address, encryptPassphrase string) (armor string, err error) { - panic("implement me") + byAddress, err := a.KeyByAddress(address) + if err != nil { + return "", err + } + + return a.ExportPrivKeyArmor(byAddress.GetName(), encryptPassphrase) } func (a altKeyring) ImportPrivKey(uid, armor, passphrase string) error { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index afbfae139fb..45aaddb6b4d 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -299,6 +299,34 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { assert.NoError(t, err) } +func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "theId" + mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) + require.NoError(t, err) + + passphrase := "somePass" + armor, err := keyring.ExportPrivKeyArmorByAddress(mnemonic.GetAddress(), passphrase) + require.NoError(t, err) + + // Should fail importing private key on existing key. + err = keyring.ImportPrivKey(uid, armor, passphrase) + require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", uid)) + + newUid := "theNewId" + // Should fail importing with wrong password + err = keyring.ImportPrivKey(newUid, armor, "wrongPass") + require.EqualError(t, err, "failed to decrypt private key: ciphertext decryption failed") + + err = keyring.ImportPrivKey(newUid, armor, passphrase) + assert.NoError(t, err) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) From 482f55fa71530f9821a2d18993da42918da251f2 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 30 Mar 2020 16:50:30 +0200 Subject: [PATCH 026/148] finish implementing altKeyring --- crypto/keyring/altkeyring.go | 47 +++++++++++++++++++++++++++---- crypto/keyring/altkeyring_test.go | 46 ++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 5 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index e9ed4da4800..1dde943d236 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -6,14 +6,13 @@ import ( "sort" "strings" - "github.com/cosmos/cosmos-sdk/crypto/keys/mintkey" - "github.com/99designs/keyring" "github.com/pkg/errors" cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" "github.com/cosmos/cosmos-sdk/crypto" "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/crypto/keys/mintkey" "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/go-bip39" @@ -131,11 +130,25 @@ type altKeyring struct { } func (a altKeyring) ExportPubKeyArmor(uid string) (string, error) { - panic("implement me") + bz, err := a.Key(uid) + if err != nil { + return "", err + } + + if bz == nil { + return "", fmt.Errorf("no key to export with name: %s", uid) + } + + return mintkey.ArmorPubKeyBytes(bz.GetPubKey().Bytes(), string(bz.GetAlgo())), nil } func (a altKeyring) ExportPubKeyArmorByAddress(address types.Address) (string, error) { - panic("implement me") + info, err := a.KeyByAddress(address) + if err != nil { + return "", err + } + + return a.ExportPubKeyArmor(info.GetName()) } func (a altKeyring) ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) { @@ -214,7 +227,31 @@ func (a altKeyring) hasKey(name string) bool { } func (a altKeyring) ImportPubKey(uid string, armor string) error { - panic("implement me") + bz, _ := a.Key(uid) + if bz != nil { + pubkey := bz.GetPubKey() + + if len(pubkey.Bytes()) > 0 { + return fmt.Errorf("cannot overwrite data for name: %s", uid) + } + } + + pubBytes, algo, err := mintkey.UnarmorPubKeyBytes(armor) + if err != nil { + return err + } + + pubKey, err := cryptoAmino.PubKeyFromBytes(pubBytes) + if err != nil { + return err + } + + _, err = a.writeOfflineKey(uid, pubKey, SigningAlgo(algo)) + if err != nil { + return err + } + + return nil } func (a altKeyring) Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error) { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 45aaddb6b4d..145e115ff24 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -327,6 +327,52 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { assert.NoError(t, err) } +func TestAltKeyring_ImportExportPubKey(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "theId" + _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) + require.NoError(t, err) + + armor, err := keyring.ExportPubKeyArmor(uid) + require.NoError(t, err) + + // Should fail importing private key on existing key. + err = keyring.ImportPubKey(uid, armor) + require.EqualError(t, err, fmt.Sprintf("cannot overwrite data for name: %s", uid)) + + newUid := "theNewId" + err = keyring.ImportPubKey(newUid, armor) + assert.NoError(t, err) +} + +func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "theId" + mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) + require.NoError(t, err) + + armor, err := keyring.ExportPubKeyArmorByAddress(mnemonic.GetAddress()) + require.NoError(t, err) + + // Should fail importing private key on existing key. + err = keyring.ImportPubKey(uid, armor) + require.EqualError(t, err, fmt.Sprintf("cannot overwrite data for name: %s", uid)) + + newUid := "theNewId" + err = keyring.ImportPubKey(newUid, armor) + assert.NoError(t, err) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) From 64349603e29aedf5e212bcc346665802d51336e0 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 30 Mar 2020 16:56:05 +0200 Subject: [PATCH 027/148] refactor thekey --- crypto/keyring/altkeyring_test.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 145e115ff24..24a7ac08c92 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -16,6 +16,8 @@ import ( "github.com/cosmos/go-bip39" ) +const someKey = "theKey" + var unsupportedAlgo = AltSigningAlgo{ Name: "unsupported", DeriveKey: nil, @@ -111,7 +113,7 @@ func TestAltKeyring_Get(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := "theKey" + uid := someKey mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -127,7 +129,7 @@ func TestAltKeyring_KeyByAddress(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := "theKey" + uid := someKey mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -143,7 +145,7 @@ func TestAltKeyring_Delete(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := "theKey" + uid := someKey _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -166,7 +168,7 @@ func TestAltKeyring_DeleteByAddress(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := "theKey" + uid := someKey mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) From d86b467dc203ca183401ef5684f0597c0a337a97 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 30 Mar 2020 17:05:26 +0200 Subject: [PATCH 028/148] fix the tests --- crypto/keyring/altkeyring_test.go | 47 ++++++++++++++++--------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 24a7ac08c92..0bb58ec7c2f 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -16,7 +16,10 @@ import ( "github.com/cosmos/go-bip39" ) -const someKey = "theKey" +const ( + someKey = "theKey" + theId = "theId" +) var unsupportedAlgo = AltSigningAlgo{ Name: "unsupported", @@ -70,16 +73,16 @@ func TestAltKeyring_NewAccount(t *testing.T) { mnemonic, err := bip39.NewMnemonic(entropy) require.NoError(t, err) - theUid := "newUid" + uid := "newUid" // Fails on creating unsupported SigningAlgo - info, err := keyring.NewAccount(theUid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), unsupportedAlgo) + _, err = keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), unsupportedAlgo) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) - info, err = keyring.NewAccount(theUid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), AltSecp256k1) + info, err := keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), AltSecp256k1) require.NoError(t, err) - require.Equal(t, theUid, info.GetName()) + require.Equal(t, uid, info.GetName()) list, err := keyring.List() require.NoError(t, err) @@ -94,16 +97,16 @@ func TestAltKeyring_SaveLedgerKey(t *testing.T) { require.NoError(t, err) // Test unsupported Algo - i1, err := keyring.SaveLedgerKey("key", unsupportedAlgo, "cosmos", 0, 0) + _, err = keyring.SaveLedgerKey("key", unsupportedAlgo, "cosmos", 0, 0) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) - i1, err = keyring.SaveLedgerKey("key", AltSecp256k1, "cosmos", 0, 0) + info, err := keyring.SaveLedgerKey("key", AltSecp256k1, "cosmos", 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", info.GetName()) } func TestAltKeyring_Get(t *testing.T) { @@ -280,7 +283,7 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := "theId" + uid := theId _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -292,12 +295,12 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { err = keyring.ImportPrivKey(uid, armor, passphrase) require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", uid)) - newUid := "theNewId" + newUID := "theNewId" // Should fail importing with wrong password - err = keyring.ImportPrivKey(newUid, armor, "wrongPass") + err = keyring.ImportPrivKey(newUID, armor, "wrongPass") require.EqualError(t, err, "failed to decrypt private key: ciphertext decryption failed") - err = keyring.ImportPrivKey(newUid, armor, passphrase) + err = keyring.ImportPrivKey(newUID, armor, passphrase) assert.NoError(t, err) } @@ -308,7 +311,7 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := "theId" + uid := theId mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -320,12 +323,12 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { err = keyring.ImportPrivKey(uid, armor, passphrase) require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", uid)) - newUid := "theNewId" + newUID := "theNewId" // Should fail importing with wrong password - err = keyring.ImportPrivKey(newUid, armor, "wrongPass") + err = keyring.ImportPrivKey(newUID, armor, "wrongPass") require.EqualError(t, err, "failed to decrypt private key: ciphertext decryption failed") - err = keyring.ImportPrivKey(newUid, armor, passphrase) + err = keyring.ImportPrivKey(newUID, armor, passphrase) assert.NoError(t, err) } @@ -336,7 +339,7 @@ func TestAltKeyring_ImportExportPubKey(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := "theId" + uid := theId _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -347,8 +350,8 @@ func TestAltKeyring_ImportExportPubKey(t *testing.T) { err = keyring.ImportPubKey(uid, armor) require.EqualError(t, err, fmt.Sprintf("cannot overwrite data for name: %s", uid)) - newUid := "theNewId" - err = keyring.ImportPubKey(newUid, armor) + newUID := "theNewId" + err = keyring.ImportPubKey(newUID, armor) assert.NoError(t, err) } @@ -359,7 +362,7 @@ func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := "theId" + uid := theId mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -370,8 +373,8 @@ func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { err = keyring.ImportPubKey(uid, armor) require.EqualError(t, err, fmt.Sprintf("cannot overwrite data for name: %s", uid)) - newUid := "theNewId" - err = keyring.ImportPubKey(newUid, armor) + newUID := "theNewId" + err = keyring.ImportPubKey(newUID, armor) assert.NoError(t, err) } From a0304e5cfd63b93f1f3750f4e14f7e4e5da5be94 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 30 Mar 2020 17:15:36 +0200 Subject: [PATCH 029/148] fixt ci linter errors --- crypto/keyring/altkeyring_test.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 0bb58ec7c2f..9f95cd3fe38 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -18,7 +18,8 @@ import ( const ( someKey = "theKey" - theId = "theId" + theID = "theID" + otherID = "otherID" ) var unsupportedAlgo = AltSigningAlgo{ @@ -283,7 +284,7 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := theId + uid := theID _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -295,7 +296,7 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { err = keyring.ImportPrivKey(uid, armor, passphrase) require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", uid)) - newUID := "theNewId" + newUID := otherID // Should fail importing with wrong password err = keyring.ImportPrivKey(newUID, armor, "wrongPass") require.EqualError(t, err, "failed to decrypt private key: ciphertext decryption failed") @@ -311,7 +312,7 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := theId + uid := theID mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -323,7 +324,7 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { err = keyring.ImportPrivKey(uid, armor, passphrase) require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", uid)) - newUID := "theNewId" + newUID := otherID // Should fail importing with wrong password err = keyring.ImportPrivKey(newUID, armor, "wrongPass") require.EqualError(t, err, "failed to decrypt private key: ciphertext decryption failed") @@ -339,7 +340,7 @@ func TestAltKeyring_ImportExportPubKey(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := theId + uid := theID _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -350,7 +351,7 @@ func TestAltKeyring_ImportExportPubKey(t *testing.T) { err = keyring.ImportPubKey(uid, armor) require.EqualError(t, err, fmt.Sprintf("cannot overwrite data for name: %s", uid)) - newUID := "theNewId" + newUID := otherID err = keyring.ImportPubKey(newUID, armor) assert.NoError(t, err) } @@ -362,7 +363,7 @@ func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := theId + uid := theID mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -373,7 +374,7 @@ func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { err = keyring.ImportPubKey(uid, armor) require.EqualError(t, err, fmt.Sprintf("cannot overwrite data for name: %s", uid)) - newUID := "theNewId" + newUID := otherID err = keyring.ImportPubKey(newUID, armor) assert.NoError(t, err) } From 717dae384c60a27c0a9f7a4dc20be305d04c8847 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 30 Mar 2020 19:20:10 +0200 Subject: [PATCH 030/148] fix other lint --- crypto/keyring/altkeyring_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 9f95cd3fe38..cf3095a3670 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -199,7 +199,7 @@ func TestAltKeyring_SavePubKey(t *testing.T) { require.NoError(t, err) require.Empty(t, list) - key := "offline" + key := someKey priv := ed25519.GenPrivKey() pub := priv.PubKey() From f58970d9ef5c0a48e8f2b8dece41a29bbadf9a23 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 26 Mar 2020 11:40:29 +0100 Subject: [PATCH 031/148] New keyring interface WIP --- crypto/keyring/keyring.go | 64 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 3db8c3d433a..926d4515f56 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -14,6 +14,7 @@ import ( "github.com/pkg/errors" "github.com/tendermint/crypto/bcrypt" + "github.com/tendermint/tendermint/crypto" tmcrypto "github.com/tendermint/tendermint/crypto" cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" @@ -39,6 +40,69 @@ const ( var _ Keybase = keyringKeybase{} +// Keyring exposes operations on a generic keystore +type Keyring interface { + + // List all keys. + List() ([]Info, error) + + // Key and KeyByAddress return keys by uid and address respectively. + Key(uid string) (Info, error) + KeyByAddress(address types.Address) (Info, error) + + // Delete and DeleteByAddress remove keys. + Delete(uid string) error + DeleteByAddress(address types.Address) error + + // NewMnemonic generates a new mnemonic, derives a hierarchical deterministic + // key from that, and persists it to storage. Returns the generated mnemonic and the key + // Info. It returns an error if it fails to generate a key for the given algo type, or if + // another key is already stored under the same name. + NewMnemonic(uid string, language Language, algo SigningAlgo) (Info, string, error) + + // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. + NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SigningAlgo) (Info, error) + + // SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. + SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) + + // SavePubKey stores a public key and returns the persisted Info structure. + SavePubKey(uid string, pubkey crypto.PubKey, algo SigningAlgo) (Info, error) + + // SaveMultisig stores, stores, and returns a new multsig (offline) key reference + SaveMultisig(uid string, pubkey crypto.PubKey) (Info, error) + + // SupportedAlgos returns a list of signing algorithms supported by the keybase + SupportedAlgos() []SigningAlgo + + // SupportedAlgosLedger returns a list of signing algorithms supported by the keybase's ledger integration + SupportedAlgosLedger() []SigningAlgo +} + +// Signer is implemented by key stores that want to provide signing capabilities. +type Signer interface { + // Sign and SignByAddress sign byte messages with a user key. + Sign(uid string, msg []byte) ([]byte, crypto.PubKey, error) + SignByAddress(address types.Address, msg []byte) ([]byte, crypto.PubKey, error) +} + +// Importer is implemented by key stores that support import of public and private keys. +type Importer interface { + ImportPrivKey(uid, armor, passphrase string) error + ImportPubKey(uid string, armor string) error +} + +// Exporter is implemented by key stores that support export of public and private keys. +type Exporter interface { + // Export public key + ExportPubKeyArmor(uid string) (string, error) + ExportPubKeyArmorByAddress(address types.Address) (string, error) + // 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. + ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) + ExportPrivKeyArmorByAddress(address types.Address, encryptPassphrase string) (armor string, err error) +} + // keyringKeybase implements the Keybase interface by using the Keyring library // for account key persistence. type keyringKeybase struct { From 1ff68301a465641d893337b3b071da840e1d8d83 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 26 Mar 2020 17:59:04 +0100 Subject: [PATCH 032/148] temp commit --- crypto/keyring/altkeyring.go | 103 ++++++++++++++++++++++++++++++ crypto/keyring/altkeyring_test.go | 1 + crypto/keyring/keyring.go | 46 ++++++------- 3 files changed, 127 insertions(+), 23 deletions(-) create mode 100644 crypto/keyring/altkeyring.go create mode 100644 crypto/keyring/altkeyring_test.go diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go new file mode 100644 index 00000000000..12f2b6d7cff --- /dev/null +++ b/crypto/keyring/altkeyring.go @@ -0,0 +1,103 @@ +package keyring + +import ( + "github.com/99designs/keyring" + "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/go-bip39" + tmcrypto "github.com/tendermint/tendermint/crypto" +) + +var ( + _ Keyring = &altKeyring{} +) + +type altKeyring struct { + db keyring.Keyring +} + +func (a altKeyring) List() ([]Info, error) { + panic("implement me") +} + +func (a altKeyring) NewMnemonic(uid string, language Language, algo SigningAlgo) (Info, string, error) { + if language != English { + return nil, "", ErrUnsupportedLanguage + } + + //if !IsSupportedAlgorithm(a.SupportedAlgos(), algo) { + // return nil, "", ErrUnsupportedSigningAlgo + //} + + // Default number of words (24): This generates a mnemonic directly from the + // number of words by reading system entropy. + entropy, err := bip39.NewEntropy(defaultEntropySize) + if err != nil { + return nil, "", err + } + + mnemonic, err := bip39.NewMnemonic(entropy) + if err != nil { + return nil, "", err + } + + info, err := a.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), algo) + if err != nil { + return nil, "", err + } + + return info, mnemonic, err +} + +func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase string, hdPath string, algo SigningAlgo) (Info, error) { + // create master key and derive first key for keyring + derivedPriv, err := StdDeriveKey(mnemonic, bip39Passphrase, hdPath, algo) + if err != nil { + return nil, err + } + + privKey, err := StdPrivKeyGen(derivedPriv, algo) + if err != nil { + return nil, err + } + + var info Info + + //if encryptPasswd != "" { + info = a.writeLocalKey(uid, privKey, encryptPasswd, algo) + //} else { + // info = a.writeOfflineKey(keyWriter, name, privKey.PubKey(), algo) + //} + + return info, nil +} + +func (a altKeyring) writeLocalKey(name string, priv tmcrypto.PrivKey, _ string, algo SigningAlgo) Info { + // encrypt private key using keyring + pub := priv.PubKey() + info := newLocalInfo(name, pub, string(priv.Bytes()), algo) + + a.writeInfo(name, info) + return info +} + +func (a altKeyring) writeInfo(name string, info Info) { + // write the info by key + key := infoKey(name) + serializedInfo := marshalInfo(info) + + err := a.db.Set(keyring.Item{ + Key: string(key), + Data: serializedInfo, + }) + if err != nil { + panic(err) + } + + err = a.db.Set(keyring.Item{ + Key: string(addrKey(info.GetAddress())), + Data: key, + }) + if err != nil { + panic(err) + } +} diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go new file mode 100644 index 00000000000..cc6ea738dcf --- /dev/null +++ b/crypto/keyring/altkeyring_test.go @@ -0,0 +1 @@ +package keyring diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 926d4515f56..ffa3af87ca6 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -42,18 +42,17 @@ var _ Keybase = keyringKeybase{} // Keyring exposes operations on a generic keystore type Keyring interface { - // List all keys. List() ([]Info, error) - // Key and KeyByAddress return keys by uid and address respectively. - Key(uid string) (Info, error) - KeyByAddress(address types.Address) (Info, error) - - // Delete and DeleteByAddress remove keys. - Delete(uid string) error - DeleteByAddress(address types.Address) error - + //// Key and KeyByAddress return keys by uid and address respectively. + //Key(uid string) (Info, error) + //KeyByAddress(address types.Address) (Info, error) + // + //// Delete and DeleteByAddress remove keys. + //Delete(uid string) error + //DeleteByAddress(address types.Address) error + // // NewMnemonic generates a new mnemonic, derives a hierarchical deterministic // key from that, and persists it to storage. Returns the generated mnemonic and the key // Info. It returns an error if it fails to generate a key for the given algo type, or if @@ -63,20 +62,21 @@ type Keyring interface { // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SigningAlgo) (Info, error) - // SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. - SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) - - // SavePubKey stores a public key and returns the persisted Info structure. - SavePubKey(uid string, pubkey crypto.PubKey, algo SigningAlgo) (Info, error) - - // SaveMultisig stores, stores, and returns a new multsig (offline) key reference - SaveMultisig(uid string, pubkey crypto.PubKey) (Info, error) - - // SupportedAlgos returns a list of signing algorithms supported by the keybase - SupportedAlgos() []SigningAlgo - - // SupportedAlgosLedger returns a list of signing algorithms supported by the keybase's ledger integration - SupportedAlgosLedger() []SigningAlgo + // + //// SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. + //SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) + // + //// SavePubKey stores a public key and returns the persisted Info structure. + //SavePubKey(uid string, pubkey crypto.PubKey, algo SigningAlgo) (Info, error) + // + //// SaveMultisig stores, stores, and returns a new multsig (offline) key reference + //SaveMultisig(uid string, pubkey crypto.PubKey) (Info, error) + // + //// SupportedAlgos returns a list of signing algorithms supported by the keybase + //SupportedAlgos() []SigningAlgo + // + //// SupportedAlgosLedger returns a list of signing algorithms supported by the keybase's ledger integration + //SupportedAlgosLedger() []SigningAlgo } // Signer is implemented by key stores that want to provide signing capabilities. From 21121cb1516c97d8a4e51b31136e0bef8aefb75c Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 26 Mar 2020 21:55:40 +0100 Subject: [PATCH 033/148] temp commit --- crypto/keyring/altkeyring.go | 11 ++++------- crypto/keyring/altkeyring_test.go | 5 +++++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 12f2b6d7cff..0cce8b69a63 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -62,21 +62,18 @@ func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase stri var info Info - //if encryptPasswd != "" { - info = a.writeLocalKey(uid, privKey, encryptPasswd, algo) - //} else { - // info = a.writeOfflineKey(keyWriter, name, privKey.PubKey(), algo) - //} + info = a.writeLocalKey(uid, privKey, algo) return info, nil } -func (a altKeyring) writeLocalKey(name string, priv tmcrypto.PrivKey, _ string, algo SigningAlgo) Info { +func (a altKeyring) writeLocalKey(name string, priv tmcrypto.PrivKey, algo SigningAlgo) Info { // encrypt private key using keyring pub := priv.PubKey() - info := newLocalInfo(name, pub, string(priv.Bytes()), algo) + info := newLocalInfo(name, pub, string(priv.Bytes()), algo) a.writeInfo(name, info) + return info } diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index cc6ea738dcf..7be6d2cff8e 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -1 +1,6 @@ package keyring + +import "testing" + +func TestAltKeyring_List(t *testing.T) { +} \ No newline at end of file From f3e7d8ac3f20f6bcc5906b7de55f9b891a561d65 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 26 Mar 2020 22:33:46 +0100 Subject: [PATCH 034/148] add test for list --- crypto/keyring/altkeyring.go | 132 +++++++++++++++++++++++++++++- crypto/keyring/altkeyring_test.go | 19 ++++- crypto/keyring/keyring.go | 64 --------------- 3 files changed, 148 insertions(+), 67 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 0cce8b69a63..dc9ee58bc17 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -1,6 +1,13 @@ package keyring import ( + "fmt" + "io" + "sort" + "strings" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/99designs/keyring" "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/go-bip39" @@ -11,12 +18,135 @@ var ( _ Keyring = &altKeyring{} ) +// Keyring exposes operations on a generic keystore +type Keyring interface { + // List all keys. + List() ([]Info, error) + + //// Key and KeyByAddress return keys by uid and address respectively. + //Key(uid string) (Info, error) + //KeyByAddress(address types.Address) (Info, error) + // + //// Delete and DeleteByAddress remove keys. + //Delete(uid string) error + //DeleteByAddress(address types.Address) error + + // NewMnemonic generates a new mnemonic, derives a hierarchical deterministic + // key from that, and persists it to storage. Returns the generated mnemonic and the key + // Info. It returns an error if it fails to generate a key for the given algo type, or if + // another key is already stored under the same name. + NewMnemonic(uid string, language Language, algo SigningAlgo) (Info, string, error) + + // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. + NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SigningAlgo) (Info, error) + + // + //// SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. + //SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) + // + //// SavePubKey stores a public key and returns the persisted Info structure. + //SavePubKey(uid string, pubkey crypto.PubKey, algo SigningAlgo) (Info, error) + // + //// SaveMultisig stores, stores, and returns a new multsig (offline) key reference + //SaveMultisig(uid string, pubkey crypto.PubKey) (Info, error) + // + //// SupportedAlgos returns a list of signing algorithms supported by the keybase + //SupportedAlgos() []SigningAlgo + // + //// SupportedAlgosLedger returns a list of signing algorithms supported by the keybase's ledger integration + //SupportedAlgosLedger() []SigningAlgo +} + +// Signer is implemented by key stores that want to provide signing capabilities. +type Signer interface { + // Sign and SignByAddress sign byte messages with a user key. + Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error) + SignByAddress(address types.Address, msg []byte) ([]byte, tmcrypto.PubKey, error) +} + +// Importer is implemented by key stores that support import of public and private keys. +type Importer interface { + ImportPrivKey(uid, armor, passphrase string) error + ImportPubKey(uid string, armor string) error +} + +// Exporter is implemented by key stores that support export of public and private keys. +type Exporter interface { + // Export public key + ExportPubKeyArmor(uid string) (string, error) + ExportPubKeyArmorByAddress(address types.Address) (string, error) + // 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. + ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) + ExportPrivKeyArmorByAddress(address types.Address, encryptPassphrase string) (armor string, err error) +} + +// NewKeyring creates a new instance of a keyring. Keybase +// options can be applied when generating this new Keybase. +// Available backends are "os", "file", "kwallet", "pass", "test". +func NewAltKeyring( + appName, backend, rootDir string, userInput io.Reader, opts ...KeybaseOption, +) (Keyring, error) { + + var db keyring.Keyring + var err error + + switch backend { + case BackendTest: + db, err = keyring.Open(lkbToKeyringConfig(appName, rootDir, nil, true)) + case BackendFile: + db, err = keyring.Open(newFileBackendKeyringConfig(appName, rootDir, userInput)) + case BackendOS: + db, err = keyring.Open(lkbToKeyringConfig(appName, rootDir, userInput, false)) + case BackendKWallet: + db, err = keyring.Open(newKWalletBackendKeyringConfig(appName, rootDir, userInput)) + case BackendPass: + db, err = keyring.Open(newPassBackendKeyringConfig(appName, rootDir, userInput)) + default: + return nil, fmt.Errorf("unknown keyring backend %v", backend) + } + + if err != nil { + return nil, err + } + + return altKeyring{db: db}, nil +} + type altKeyring struct { db keyring.Keyring } func (a altKeyring) List() ([]Info, error) { - panic("implement me") + var res []Info + keys, err := a.db.Keys() + if err != nil { + return nil, err + } + + sort.Strings(keys) + + for _, key := range keys { + if strings.HasSuffix(key, infoSuffix) { + rawInfo, err := a.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) + } + } + + return res, nil } func (a altKeyring) NewMnemonic(uid string, language Language, algo SigningAlgo) (Info, string, error) { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 7be6d2cff8e..b7a623f5032 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -1,6 +1,21 @@ package keyring -import "testing" +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/tests" +) func TestAltKeyring_List(t *testing.T) { -} \ No newline at end of file + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + list, err := keyring.List() + require.NoError(t, err) + require.Len(t, list, 0) +} diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index ffa3af87ca6..3db8c3d433a 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -14,7 +14,6 @@ import ( "github.com/pkg/errors" "github.com/tendermint/crypto/bcrypt" - "github.com/tendermint/tendermint/crypto" tmcrypto "github.com/tendermint/tendermint/crypto" cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" @@ -40,69 +39,6 @@ const ( var _ Keybase = keyringKeybase{} -// Keyring exposes operations on a generic keystore -type Keyring interface { - // List all keys. - List() ([]Info, error) - - //// Key and KeyByAddress return keys by uid and address respectively. - //Key(uid string) (Info, error) - //KeyByAddress(address types.Address) (Info, error) - // - //// Delete and DeleteByAddress remove keys. - //Delete(uid string) error - //DeleteByAddress(address types.Address) error - // - // NewMnemonic generates a new mnemonic, derives a hierarchical deterministic - // key from that, and persists it to storage. Returns the generated mnemonic and the key - // Info. It returns an error if it fails to generate a key for the given algo type, or if - // another key is already stored under the same name. - NewMnemonic(uid string, language Language, algo SigningAlgo) (Info, string, error) - - // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. - NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SigningAlgo) (Info, error) - - // - //// SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. - //SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) - // - //// SavePubKey stores a public key and returns the persisted Info structure. - //SavePubKey(uid string, pubkey crypto.PubKey, algo SigningAlgo) (Info, error) - // - //// SaveMultisig stores, stores, and returns a new multsig (offline) key reference - //SaveMultisig(uid string, pubkey crypto.PubKey) (Info, error) - // - //// SupportedAlgos returns a list of signing algorithms supported by the keybase - //SupportedAlgos() []SigningAlgo - // - //// SupportedAlgosLedger returns a list of signing algorithms supported by the keybase's ledger integration - //SupportedAlgosLedger() []SigningAlgo -} - -// Signer is implemented by key stores that want to provide signing capabilities. -type Signer interface { - // Sign and SignByAddress sign byte messages with a user key. - Sign(uid string, msg []byte) ([]byte, crypto.PubKey, error) - SignByAddress(address types.Address, msg []byte) ([]byte, crypto.PubKey, error) -} - -// Importer is implemented by key stores that support import of public and private keys. -type Importer interface { - ImportPrivKey(uid, armor, passphrase string) error - ImportPubKey(uid string, armor string) error -} - -// Exporter is implemented by key stores that support export of public and private keys. -type Exporter interface { - // Export public key - ExportPubKeyArmor(uid string) (string, error) - ExportPubKeyArmorByAddress(address types.Address) (string, error) - // 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. - ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) - ExportPrivKeyArmorByAddress(address types.Address, encryptPassphrase string) (armor string, err error) -} - // keyringKeybase implements the Keybase interface by using the Keyring library // for account key persistence. type keyringKeybase struct { From 518ace9b895263e2f38e59ea38924fb14f4730b8 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 26 Mar 2020 22:37:40 +0100 Subject: [PATCH 035/148] test adding new key --- crypto/keyring/altkeyring.go | 5 ++--- crypto/keyring/altkeyring_test.go | 7 +++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index dc9ee58bc17..cfa6f200313 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -6,12 +6,12 @@ import ( "sort" "strings" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/99designs/keyring" "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/go-bip39" tmcrypto "github.com/tendermint/tendermint/crypto" + + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) var ( @@ -40,7 +40,6 @@ type Keyring interface { // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SigningAlgo) (Info, error) - // //// SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. //SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) // diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index b7a623f5032..582a86c1e80 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -18,4 +18,11 @@ func TestAltKeyring_List(t *testing.T) { list, err := keyring.List() require.NoError(t, err) require.Len(t, list, 0) + + _, _, err = keyring.NewMnemonic("theKey", English, Secp256k1) + require.NoError(t, err) + + list, err = keyring.List() + require.NoError(t, err) + require.Len(t, list, 1) } From 195de908b2ce33661f4a847ddecdc25dd0116e5a Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 26 Mar 2020 22:47:51 +0100 Subject: [PATCH 036/148] add test for list --- crypto/keyring/altkeyring_test.go | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 582a86c1e80..f130e87c992 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -17,12 +17,23 @@ func TestAltKeyring_List(t *testing.T) { list, err := keyring.List() require.NoError(t, err) - require.Len(t, list, 0) + require.Empty(t, list) - _, _, err = keyring.NewMnemonic("theKey", English, Secp256k1) + // Create 3 keys + uid1, uid2, uid3 := "Zkey", "Bkey", "Rkey" + _, _, err = keyring.NewMnemonic(uid1, English, Secp256k1) + require.NoError(t, err) + _, _, err = keyring.NewMnemonic(uid2, English, Secp256k1) + require.NoError(t, err) + _, _, err = keyring.NewMnemonic(uid3, English, Secp256k1) require.NoError(t, err) list, err = keyring.List() require.NoError(t, err) - require.Len(t, list, 1) + require.Len(t, list, 3) + + // Check they are in alphabetical order + require.Equal(t, uid2, list[0].GetName()) + require.Equal(t, uid3, list[1].GetName()) + require.Equal(t, uid1, list[2].GetName()) } From cdc534ce10b385394cf2eb3d79eea3f7d2c1db36 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 26 Mar 2020 23:12:00 +0100 Subject: [PATCH 037/148] implement and test Key --- crypto/keyring/altkeyring.go | 20 ++++++++++++++++++-- crypto/keyring/altkeyring_test.go | 20 ++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index cfa6f200313..1e82116511b 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -23,8 +23,9 @@ type Keyring interface { // List all keys. List() ([]Info, error) - //// Key and KeyByAddress return keys by uid and address respectively. - //Key(uid string) (Info, error) + // Key and KeyByAddress return keys by uid and address respectively. + Key(uid string) (Info, error) + //KeyByAddress(address types.Address) (Info, error) // //// Delete and DeleteByAddress remove keys. @@ -196,6 +197,21 @@ func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase stri return info, nil } +func (a altKeyring) Key(uid string) (Info, error) { + key := infoKey(uid) + + bs, err := a.db.Get(string(key)) + if err != nil { + return nil, err + } + + if len(bs.Data) == 0 { + return nil, sdkerrors.Wrap(sdkerrors.ErrKeyNotFound, uid) + } + + return unmarshalInfo(bs.Data) +} + func (a altKeyring) writeLocalKey(name string, priv tmcrypto.PrivKey, algo SigningAlgo) Info { // encrypt private key using keyring pub := priv.PubKey() diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index f130e87c992..a458748da24 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -37,3 +37,23 @@ func TestAltKeyring_List(t *testing.T) { require.Equal(t, uid3, list[1].GetName()) require.Equal(t, uid1, list[2].GetName()) } + +func TestAltKeyring_Get(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "theKey" + mnemonic, _, err := keyring.NewMnemonic(uid, English, Secp256k1) + require.NoError(t, err) + + key, err := keyring.Key(uid) + require.NoError(t, err) + require.Equal(t, key.GetName(), mnemonic.GetName()) + require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) + require.Equal(t, key.GetPubKey(), mnemonic.GetPubKey()) + require.Equal(t, key.GetAlgo(), mnemonic.GetAlgo()) + require.Equal(t, key.GetType(), mnemonic.GetType()) +} From 516ec8bd96be65c229d64d174358f97915034a39 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 26 Mar 2020 23:29:27 +0100 Subject: [PATCH 038/148] create and test GetByAddress --- crypto/keyring/altkeyring.go | 20 +++++++++++++++++++- crypto/keyring/altkeyring_test.go | 20 ++++++++++++++++++++ crypto/keyring/db_keybase.go | 2 +- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 1e82116511b..5d68dbb5c62 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -25,8 +25,8 @@ type Keyring interface { // Key and KeyByAddress return keys by uid and address respectively. Key(uid string) (Info, error) + KeyByAddress(address types.Address) (Info, error) - //KeyByAddress(address types.Address) (Info, error) // //// Delete and DeleteByAddress remove keys. //Delete(uid string) error @@ -117,6 +117,24 @@ type altKeyring struct { db keyring.Keyring } +func (a altKeyring) KeyByAddress(address types.Address) (Info, error) { + ik, err := a.db.Get(string(addrKey(address))) + if err != nil { + return nil, err + } + + if len(ik.Data) == 0 { + return nil, fmt.Errorf("key with address %s not found", address) + } + + bs, err := a.db.Get(string(ik.Data)) + if err != nil { + return nil, err + } + + return unmarshalInfo(bs.Data) +} + func (a altKeyring) List() ([]Info, error) { var res []Info keys, err := a.db.Keys() diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index a458748da24..d0af28c97f7 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -51,6 +51,26 @@ func TestAltKeyring_Get(t *testing.T) { key, err := keyring.Key(uid) require.NoError(t, err) + requireEqualInfo(t, mnemonic, key) +} + +func TestAltKeyring_KeyByAddress(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "theKey" + mnemonic, _, err := keyring.NewMnemonic(uid, English, Secp256k1) + require.NoError(t, err) + + key, err := keyring.KeyByAddress(mnemonic.GetAddress()) + require.NoError(t, err) + requireEqualInfo(t, key, mnemonic) +} + +func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) require.Equal(t, key.GetPubKey(), mnemonic.GetPubKey()) diff --git a/crypto/keyring/db_keybase.go b/crypto/keyring/db_keybase.go index e1513b38e08..5e7ffe0fca3 100644 --- a/crypto/keyring/db_keybase.go +++ b/crypto/keyring/db_keybase.go @@ -417,7 +417,7 @@ func (kb dbKeybase) writeInfo(name string, info Info) { kb.db.SetSync(addrKey(info.GetAddress()), key) } -func addrKey(address types.AccAddress) []byte { +func addrKey(address types.Address) []byte { return []byte(fmt.Sprintf("%s.%s", address.String(), addressSuffix)) } From 1d795bf1c6d5d9d174d307be89b9fa9b67fdc4f5 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 11:29:05 +0100 Subject: [PATCH 039/148] add delete function --- crypto/keyring/altkeyring.go | 22 ++++++++++++++++++++-- crypto/keyring/altkeyring_test.go | 23 +++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 5d68dbb5c62..a4138599a14 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -27,9 +27,8 @@ type Keyring interface { Key(uid string) (Info, error) KeyByAddress(address types.Address) (Info, error) - // //// Delete and DeleteByAddress remove keys. - //Delete(uid string) error + Delete(uid string) error //DeleteByAddress(address types.Address) error // NewMnemonic generates a new mnemonic, derives a hierarchical deterministic @@ -117,6 +116,25 @@ type altKeyring struct { db keyring.Keyring } +func (a altKeyring) Delete(uid string) error { + info, err := a.Key(uid) + if err != nil { + return err + } + + err = a.db.Remove(string(addrKey(info.GetAddress()))) + if err != nil { + return err + } + + err = a.db.Remove(string(infoKey(uid))) + if err != nil { + return err + } + + return nil +} + func (a altKeyring) KeyByAddress(address types.Address) (Info, error) { ik, err := a.db.Get(string(addrKey(address))) if err != nil { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index d0af28c97f7..1c9a7a251bb 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -70,6 +70,29 @@ func TestAltKeyring_KeyByAddress(t *testing.T) { requireEqualInfo(t, key, mnemonic) } +func TestAltKeyring_Delete(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "theKey" + _, _, err = keyring.NewMnemonic(uid, English, Secp256k1) + require.NoError(t, err) + + list, err := keyring.List() + require.NoError(t, err) + require.Len(t, list, 1) + + err = keyring.Delete(uid) + require.NoError(t, err) + + list, err = keyring.List() + require.NoError(t, err) + require.Empty(t, list) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) From 2e3a8ac9765ea32f69b6c8d2b94e53647bf7603f Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 11:38:20 +0100 Subject: [PATCH 040/148] add delete by address function --- crypto/keyring/altkeyring.go | 16 +++++++++++++++- crypto/keyring/altkeyring_test.go | 23 +++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index a4138599a14..4d685f4784a 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -29,7 +29,7 @@ type Keyring interface { //// Delete and DeleteByAddress remove keys. Delete(uid string) error - //DeleteByAddress(address types.Address) error + DeleteByAddress(address types.Address) error // NewMnemonic generates a new mnemonic, derives a hierarchical deterministic // key from that, and persists it to storage. Returns the generated mnemonic and the key @@ -116,6 +116,20 @@ type altKeyring struct { db keyring.Keyring } +func (a altKeyring) DeleteByAddress(address types.Address) error { + info, err := a.KeyByAddress(address) + if err != nil { + return err + } + + err = a.Delete(info.GetName()) + if err != nil { + return err + } + + return nil +} + func (a altKeyring) Delete(uid string) error { info, err := a.Key(uid) if err != nil { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 1c9a7a251bb..0f77defc743 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -93,6 +93,29 @@ func TestAltKeyring_Delete(t *testing.T) { require.Empty(t, list) } +func TestAltKeyring_DeleteByAddress(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "theKey" + mnemonic, _, err := keyring.NewMnemonic(uid, English, Secp256k1) + require.NoError(t, err) + + list, err := keyring.List() + require.NoError(t, err) + require.Len(t, list, 1) + + err = keyring.DeleteByAddress(mnemonic.GetAddress()) + require.NoError(t, err) + + list, err = keyring.List() + require.NoError(t, err) + require.Empty(t, list) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) From b94cfff4c51c6c3bfea2f90d581ec01abfa401cd Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 12:40:36 +0100 Subject: [PATCH 041/148] add new pub key and test --- crypto/keyring/altkeyring.go | 14 ++++++++++++-- crypto/keyring/altkeyring_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 4d685f4784a..6edb56f8636 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -43,8 +43,8 @@ type Keyring interface { //// SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. //SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) // - //// SavePubKey stores a public key and returns the persisted Info structure. - //SavePubKey(uid string, pubkey crypto.PubKey, algo SigningAlgo) (Info, error) + // SavePubKey stores a public key and returns the persisted Info structure. + SavePubKey(uid string, pubkey tmcrypto.PubKey, algo SigningAlgo) (Info, error) // //// SaveMultisig stores, stores, and returns a new multsig (offline) key reference //SaveMultisig(uid string, pubkey crypto.PubKey) (Info, error) @@ -116,6 +116,10 @@ type altKeyring struct { db keyring.Keyring } +func (a altKeyring) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo SigningAlgo) (Info, error) { + return a.writeOfflineKey(uid, pubkey, algo), nil +} + func (a altKeyring) DeleteByAddress(address types.Address) error { info, err := a.KeyByAddress(address) if err != nil { @@ -293,3 +297,9 @@ func (a altKeyring) writeInfo(name string, info Info) { panic(err) } } + +func (a altKeyring) writeOfflineKey(name string, pub tmcrypto.PubKey, algo SigningAlgo) Info { + info := newOfflineInfo(name, pub, algo) + a.writeInfo(name, info) + return info +} diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 0f77defc743..9c1724ea04d 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -3,6 +3,8 @@ package keyring import ( "testing" + "github.com/tendermint/tendermint/crypto/ed25519" + "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/tests" @@ -116,6 +118,31 @@ func TestAltKeyring_DeleteByAddress(t *testing.T) { require.Empty(t, list) } +func TestAltKeyring_SavePubKey(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + list, err := keyring.List() + require.NoError(t, err) + require.Empty(t, list) + + key := "offline" + priv := ed25519.GenPrivKey() + pub := priv.PubKey() + + info, err := keyring.SavePubKey(key, pub, Ed25519) + require.Nil(t, err) + require.Equal(t, pub, info.GetPubKey()) + require.Equal(t, key, info.GetName()) + + list, err = keyring.List() + require.NoError(t, err) + require.Equal(t, 1, len(list)) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) From de0976e632d4b98a1aa8b05d72ae69269f2be27d Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 13:43:59 +0100 Subject: [PATCH 042/148] create function for writing multisign --- client/keys/add.go | 3 +- crypto/keyring/altkeyring.go | 57 ++++++++++++++++++++++++------------ 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/client/keys/add.go b/client/keys/add.go index d8f768cc4f1..80f3bb243cb 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -117,9 +117,10 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keybase, inBuf *buf showMnemonic := !viper.GetBool(flagNoBackup) algo := keyring.SigningAlgo(viper.GetString(flagKeyAlgo)) - if algo == keyring.SigningAlgo("") { + if algo == "" { algo = keyring.Secp256k1 } + if !keyring.IsSupportedAlgorithm(kb.SupportedAlgos(), algo) { return keyring.ErrUnsupportedSigningAlgo } diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 6edb56f8636..efcd02cc155 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -42,12 +42,12 @@ type Keyring interface { //// SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. //SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) - // + // SavePubKey stores a public key and returns the persisted Info structure. SavePubKey(uid string, pubkey tmcrypto.PubKey, algo SigningAlgo) (Info, error) - // - //// SaveMultisig stores, stores, and returns a new multsig (offline) key reference - //SaveMultisig(uid string, pubkey crypto.PubKey) (Info, error) + + // SaveMultisig stores, stores, and returns a new multsig (offline) key reference + SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) // //// SupportedAlgos returns a list of signing algorithms supported by the keybase //SupportedAlgos() []SigningAlgo @@ -116,8 +116,12 @@ type altKeyring struct { db keyring.Keyring } +func (a altKeyring) SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) { + return a.writeMultisigKey(uid, pubkey) +} + func (a altKeyring) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo SigningAlgo) (Info, error) { - return a.writeOfflineKey(uid, pubkey, algo), nil + return a.writeOfflineKey(uid, pubkey, algo) } func (a altKeyring) DeleteByAddress(address types.Address) error { @@ -244,11 +248,7 @@ func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase stri return nil, err } - var info Info - - info = a.writeLocalKey(uid, privKey, algo) - - return info, nil + return a.writeLocalKey(uid, privKey, algo) } func (a altKeyring) Key(uid string) (Info, error) { @@ -266,17 +266,20 @@ func (a altKeyring) Key(uid string) (Info, error) { return unmarshalInfo(bs.Data) } -func (a altKeyring) writeLocalKey(name string, priv tmcrypto.PrivKey, algo SigningAlgo) Info { +func (a altKeyring) writeLocalKey(name string, priv tmcrypto.PrivKey, algo SigningAlgo) (Info, error) { // encrypt private key using keyring pub := priv.PubKey() info := newLocalInfo(name, pub, string(priv.Bytes()), algo) - a.writeInfo(name, info) + err := a.writeInfo(name, info) + if err != nil { + return nil, err + } - return info + return info, nil } -func (a altKeyring) writeInfo(name string, info Info) { +func (a altKeyring) writeInfo(name string, info Info) error { // write the info by key key := infoKey(name) serializedInfo := marshalInfo(info) @@ -286,7 +289,7 @@ func (a altKeyring) writeInfo(name string, info Info) { Data: serializedInfo, }) if err != nil { - panic(err) + return err } err = a.db.Set(keyring.Item{ @@ -294,12 +297,28 @@ func (a altKeyring) writeInfo(name string, info Info) { Data: key, }) if err != nil { - panic(err) + return err } + + return nil } -func (a altKeyring) writeOfflineKey(name string, pub tmcrypto.PubKey, algo SigningAlgo) Info { +func (a altKeyring) writeOfflineKey(name string, pub tmcrypto.PubKey, algo SigningAlgo) (Info, error) { info := newOfflineInfo(name, pub, algo) - a.writeInfo(name, info) - return info + err := a.writeInfo(name, info) + if err != nil { + return nil, err + } + + return info, nil +} + +func (a altKeyring) writeMultisigKey(name string, pub tmcrypto.PubKey) (Info, error) { + info := NewMultiInfo(name, pub) + err := a.writeInfo(name, info) + if err != nil { + return nil, err + } + + return info, nil } From 46a5436faf98a14af09f1c70e3e12924474bbdb2 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 14:38:40 +0100 Subject: [PATCH 043/148] use addrKeyByString --- crypto/keyring/altkeyring.go | 6 +++--- crypto/keyring/db_keybase.go | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index efcd02cc155..42dfd28814f 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -144,7 +144,7 @@ func (a altKeyring) Delete(uid string) error { return err } - err = a.db.Remove(string(addrKey(info.GetAddress()))) + err = a.db.Remove(addrKeyAsString(info.GetAddress())) if err != nil { return err } @@ -158,7 +158,7 @@ func (a altKeyring) Delete(uid string) error { } func (a altKeyring) KeyByAddress(address types.Address) (Info, error) { - ik, err := a.db.Get(string(addrKey(address))) + ik, err := a.db.Get(addrKeyAsString(address)) if err != nil { return nil, err } @@ -293,7 +293,7 @@ func (a altKeyring) writeInfo(name string, info Info) error { } err = a.db.Set(keyring.Item{ - Key: string(addrKey(info.GetAddress())), + Key: addrKeyAsString(info.GetAddress()), Data: key, }) if err != nil { diff --git a/crypto/keyring/db_keybase.go b/crypto/keyring/db_keybase.go index 5e7ffe0fca3..7bb58516f75 100644 --- a/crypto/keyring/db_keybase.go +++ b/crypto/keyring/db_keybase.go @@ -421,6 +421,10 @@ func addrKey(address types.Address) []byte { return []byte(fmt.Sprintf("%s.%s", address.String(), addressSuffix)) } +func addrKeyAsString(address types.Address) string { + return fmt.Sprintf("%s.%s", address.String(), addressSuffix) +} + func infoKey(name string) []byte { return []byte(fmt.Sprintf("%s.%s", name, infoSuffix)) } From b475b6c57473d8a425014660ced37ee621d81cb4 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 14:59:54 +0100 Subject: [PATCH 044/148] implement and test multisig --- crypto/keyring/altkeyring.go | 1 + crypto/keyring/altkeyring_test.go | 31 ++++++++++++++++++++++++++++++- crypto/keyring/db_keybase.go | 2 +- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 42dfd28814f..f3347d687e5 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -48,6 +48,7 @@ type Keyring interface { // SaveMultisig stores, stores, and returns a new multsig (offline) key reference SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) + // //// SupportedAlgos returns a list of signing algorithms supported by the keybase //SupportedAlgos() []SigningAlgo diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 9c1724ea04d..d863aad85de 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -3,6 +3,10 @@ package keyring import ( "testing" + "github.com/tendermint/tendermint/crypto" + + "github.com/tendermint/tendermint/crypto/multisig" + "github.com/tendermint/tendermint/crypto/ed25519" "github.com/stretchr/testify/require" @@ -133,7 +137,7 @@ func TestAltKeyring_SavePubKey(t *testing.T) { priv := ed25519.GenPrivKey() pub := priv.PubKey() - info, err := keyring.SavePubKey(key, pub, Ed25519) + info, err := keyring.SavePubKey(key, pub, Secp256k1) require.Nil(t, err) require.Equal(t, pub, info.GetPubKey()) require.Equal(t, key, info.GetName()) @@ -143,6 +147,31 @@ func TestAltKeyring_SavePubKey(t *testing.T) { require.Equal(t, 1, len(list)) } +func TestAltKeyring_SaveMultisig(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + mnemonic1, _, err := keyring.NewMnemonic("key1", English, Secp256k1) + require.NoError(t, err) + mnemonic2, _, err := keyring.NewMnemonic("key2", English, Secp256k1) + require.NoError(t, err) + + key := "multi" + pub := multisig.NewPubKeyMultisigThreshold(2, []crypto.PubKey{mnemonic1.GetPubKey(), mnemonic2.GetPubKey()}) + + info, err := keyring.SaveMultisig(key, pub) + require.Nil(t, err) + require.Equal(t, pub, info.GetPubKey()) + require.Equal(t, key, info.GetName()) + + list, err := keyring.List() + require.NoError(t, err) + require.Len(t, list, 3) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) diff --git a/crypto/keyring/db_keybase.go b/crypto/keyring/db_keybase.go index 7bb58516f75..f7c67e561a9 100644 --- a/crypto/keyring/db_keybase.go +++ b/crypto/keyring/db_keybase.go @@ -418,7 +418,7 @@ func (kb dbKeybase) writeInfo(name string, info Info) { } func addrKey(address types.Address) []byte { - return []byte(fmt.Sprintf("%s.%s", address.String(), addressSuffix)) + return []byte(addrKeyAsString(address)) } func addrKeyAsString(address types.Address) string { From 5f961e381e674ece9bffdba53e931ae9bab181d8 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 16:29:04 +0100 Subject: [PATCH 045/148] add test for unsupported signing algo --- crypto/keyring/altkeyring.go | 25 ++++++++++++++++++------- crypto/keyring/altkeyring_test.go | 4 ++++ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index f3347d687e5..874577cf38a 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -49,7 +49,6 @@ type Keyring interface { // SaveMultisig stores, stores, and returns a new multsig (offline) key reference SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) - // //// SupportedAlgos returns a list of signing algorithms supported by the keybase //SupportedAlgos() []SigningAlgo // @@ -85,7 +84,7 @@ type Exporter interface { // options can be applied when generating this new Keybase. // Available backends are "os", "file", "kwallet", "pass", "test". func NewAltKeyring( - appName, backend, rootDir string, userInput io.Reader, opts ...KeybaseOption, + appName, backend, rootDir string, userInput io.Reader, ) (Keyring, error) { var db keyring.Keyring @@ -110,11 +109,23 @@ func NewAltKeyring( return nil, err } - return altKeyring{db: db}, nil + return altKeyring{ + db: db, + options: altKrOptions{ + supportedAlgos: []SigningAlgo{Secp256k1}, + supportedAlgosLedger: []SigningAlgo{Secp256k1}, + }, + }, nil } type altKeyring struct { - db keyring.Keyring + db keyring.Keyring + options altKrOptions +} + +type altKrOptions struct { + supportedAlgos []SigningAlgo + supportedAlgosLedger []SigningAlgo } func (a altKeyring) SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) { @@ -213,9 +224,9 @@ func (a altKeyring) NewMnemonic(uid string, language Language, algo SigningAlgo) return nil, "", ErrUnsupportedLanguage } - //if !IsSupportedAlgorithm(a.SupportedAlgos(), algo) { - // return nil, "", ErrUnsupportedSigningAlgo - //} + if !IsSupportedAlgorithm(a.options.supportedAlgos, algo) { + return nil, "", ErrUnsupportedSigningAlgo + } // Default number of words (24): This generates a mnemonic directly from the // number of words by reading system entropy. diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index d863aad85de..816160d1e58 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -25,6 +25,10 @@ func TestAltKeyring_List(t *testing.T) { require.NoError(t, err) require.Empty(t, list) + // Fails on creating unsupported SigningAlgo + _, _, err = keyring.NewMnemonic("failing", English, Ed25519) + require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) + // Create 3 keys uid1, uid2, uid3 := "Zkey", "Bkey", "Rkey" _, _, err = keyring.NewMnemonic(uid1, English, Secp256k1) From b7047457c32acc9466dcf1f39c9e35bf17108e17 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 18:16:35 +0100 Subject: [PATCH 046/148] refactor algorithm --- crypto/keyring/alt_signing_algorithms.go | 29 ++++++++++++++++ crypto/keyring/alt_signing_algorithms_test.go | 20 +++++++++++ crypto/keyring/altkeyring.go | 34 +++++++++---------- crypto/keyring/altkeyring_test.go | 32 +++++++++-------- crypto/keyring/base_keybase.go | 1 - 5 files changed, 82 insertions(+), 34 deletions(-) create mode 100644 crypto/keyring/alt_signing_algorithms.go create mode 100644 crypto/keyring/alt_signing_algorithms_test.go diff --git a/crypto/keyring/alt_signing_algorithms.go b/crypto/keyring/alt_signing_algorithms.go new file mode 100644 index 00000000000..9c7d22072c6 --- /dev/null +++ b/crypto/keyring/alt_signing_algorithms.go @@ -0,0 +1,29 @@ +package keyring + +import "github.com/tendermint/tendermint/crypto" + +type AltSigningAlgo struct { + Name SigningAlgo + DeriveKey AltDeriveKeyFunc + PrivKeyGen AltPrivKeyGenFunc +} + +type AltDeriveKeyFunc func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) +type AltPrivKeyGenFunc func(bz []byte) crypto.PrivKey + +var ( + // Secp256k1 uses the Bitcoin secp256k1 ECDSA parameters. + AltSecp256k1 = AltSigningAlgo{Name: Secp256k1, DeriveKey: SecpDeriveKey, PrivKeyGen: SecpPrivKeyGen} +) + +type AltSigningAlgoList []AltSigningAlgo + +func (l AltSigningAlgoList) Contains(algo AltSigningAlgo) bool { + for _, cAlgo := range l { + if cAlgo.Name == algo.Name { + return true + } + } + + return false +} diff --git a/crypto/keyring/alt_signing_algorithms_test.go b/crypto/keyring/alt_signing_algorithms_test.go new file mode 100644 index 00000000000..91c2e96cf67 --- /dev/null +++ b/crypto/keyring/alt_signing_algorithms_test.go @@ -0,0 +1,20 @@ +package keyring + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAltSigningAlgoList_Contains(t *testing.T) { + list := AltSigningAlgoList{ + AltSecp256k1, + } + + notSupportedAlgo := AltSigningAlgo{ + Name: "anotherAlgo", + DeriveKey: nil, + } + assert.True(t, list.Contains(AltSecp256k1)) + assert.False(t, list.Contains(notSupportedAlgo)) +} diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 874577cf38a..c354ecaf508 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -35,10 +35,10 @@ type Keyring interface { // key from that, and persists it to storage. Returns the generated mnemonic and the key // Info. It returns an error if it fails to generate a key for the given algo type, or if // another key is already stored under the same name. - NewMnemonic(uid string, language Language, algo SigningAlgo) (Info, string, error) + NewMnemonic(uid string, language Language, algo AltSigningAlgo) (Info, string, error) // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. - NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SigningAlgo) (Info, error) + NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo AltSigningAlgo) (Info, error) //// SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. //SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) @@ -49,9 +49,6 @@ type Keyring interface { // SaveMultisig stores, stores, and returns a new multsig (offline) key reference SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) - //// SupportedAlgos returns a list of signing algorithms supported by the keybase - //SupportedAlgos() []SigningAlgo - // //// SupportedAlgosLedger returns a list of signing algorithms supported by the keybase's ledger integration //SupportedAlgosLedger() []SigningAlgo } @@ -112,8 +109,8 @@ func NewAltKeyring( return altKeyring{ db: db, options: altKrOptions{ - supportedAlgos: []SigningAlgo{Secp256k1}, - supportedAlgosLedger: []SigningAlgo{Secp256k1}, + supportedAlgos: []AltSigningAlgo{AltSecp256k1}, + supportedAlgosLedger: []AltSigningAlgo{AltSecp256k1}, }, }, nil } @@ -124,8 +121,8 @@ type altKeyring struct { } type altKrOptions struct { - supportedAlgos []SigningAlgo - supportedAlgosLedger []SigningAlgo + supportedAlgos AltSigningAlgoList + supportedAlgosLedger AltSigningAlgoList } func (a altKeyring) SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) { @@ -219,12 +216,12 @@ func (a altKeyring) List() ([]Info, error) { return res, nil } -func (a altKeyring) NewMnemonic(uid string, language Language, algo SigningAlgo) (Info, string, error) { +func (a altKeyring) NewMnemonic(uid string, language Language, algo AltSigningAlgo) (Info, string, error) { if language != English { return nil, "", ErrUnsupportedLanguage } - if !IsSupportedAlgorithm(a.options.supportedAlgos, algo) { + if !a.options.supportedAlgos.Contains(algo) { return nil, "", ErrUnsupportedSigningAlgo } @@ -248,19 +245,20 @@ func (a altKeyring) NewMnemonic(uid string, language Language, algo SigningAlgo) return info, mnemonic, err } -func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase string, hdPath string, algo SigningAlgo) (Info, error) { +func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase string, hdPath string, algo AltSigningAlgo) (Info, error) { + //if !IsSupportedAlgorithm(a.options.supportedAlgos, algo) { + // return nil, ErrUnsupportedSigningAlgo + //} + // // create master key and derive first key for keyring - derivedPriv, err := StdDeriveKey(mnemonic, bip39Passphrase, hdPath, algo) + derivedPriv, err := algo.DeriveKey(mnemonic, bip39Passphrase, hdPath) if err != nil { return nil, err } - privKey, err := StdPrivKeyGen(derivedPriv, algo) - if err != nil { - return nil, err - } + privKey := algo.PrivKeyGen(derivedPriv) - return a.writeLocalKey(uid, privKey, algo) + return a.writeLocalKey(uid, privKey, SigningAlgo(algo.Name)) } func (a altKeyring) Key(uid string) (Info, error) { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 816160d1e58..ccd019de361 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -3,17 +3,19 @@ package keyring import ( "testing" + "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" - - "github.com/tendermint/tendermint/crypto/multisig" - "github.com/tendermint/tendermint/crypto/ed25519" - - "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto/multisig" "github.com/cosmos/cosmos-sdk/tests" ) +var unsupportedAlgo = AltSigningAlgo{ + Name: "unsupported", + DeriveKey: nil, +} + func TestAltKeyring_List(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) @@ -26,16 +28,16 @@ func TestAltKeyring_List(t *testing.T) { require.Empty(t, list) // Fails on creating unsupported SigningAlgo - _, _, err = keyring.NewMnemonic("failing", English, Ed25519) + _, _, err = keyring.NewMnemonic("failing", English, unsupportedAlgo) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) // Create 3 keys uid1, uid2, uid3 := "Zkey", "Bkey", "Rkey" - _, _, err = keyring.NewMnemonic(uid1, English, Secp256k1) + _, _, err = keyring.NewMnemonic(uid1, English, AltSecp256k1) require.NoError(t, err) - _, _, err = keyring.NewMnemonic(uid2, English, Secp256k1) + _, _, err = keyring.NewMnemonic(uid2, English, AltSecp256k1) require.NoError(t, err) - _, _, err = keyring.NewMnemonic(uid3, English, Secp256k1) + _, _, err = keyring.NewMnemonic(uid3, English, AltSecp256k1) require.NoError(t, err) list, err = keyring.List() @@ -56,7 +58,7 @@ func TestAltKeyring_Get(t *testing.T) { require.NoError(t, err) uid := "theKey" - mnemonic, _, err := keyring.NewMnemonic(uid, English, Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) key, err := keyring.Key(uid) @@ -72,7 +74,7 @@ func TestAltKeyring_KeyByAddress(t *testing.T) { require.NoError(t, err) uid := "theKey" - mnemonic, _, err := keyring.NewMnemonic(uid, English, Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) key, err := keyring.KeyByAddress(mnemonic.GetAddress()) @@ -88,7 +90,7 @@ func TestAltKeyring_Delete(t *testing.T) { require.NoError(t, err) uid := "theKey" - _, _, err = keyring.NewMnemonic(uid, English, Secp256k1) + _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) list, err := keyring.List() @@ -111,7 +113,7 @@ func TestAltKeyring_DeleteByAddress(t *testing.T) { require.NoError(t, err) uid := "theKey" - mnemonic, _, err := keyring.NewMnemonic(uid, English, Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) list, err := keyring.List() @@ -158,9 +160,9 @@ func TestAltKeyring_SaveMultisig(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - mnemonic1, _, err := keyring.NewMnemonic("key1", English, Secp256k1) + mnemonic1, _, err := keyring.NewMnemonic("key1", English, AltSecp256k1) require.NoError(t, err) - mnemonic2, _, err := keyring.NewMnemonic("key2", English, Secp256k1) + mnemonic2, _, err := keyring.NewMnemonic("key2", English, AltSecp256k1) require.NoError(t, err) key := "multi" diff --git a/crypto/keyring/base_keybase.go b/crypto/keyring/base_keybase.go index c2f7952b820..3316da181e2 100644 --- a/crypto/keyring/base_keybase.go +++ b/crypto/keyring/base_keybase.go @@ -70,7 +70,6 @@ func SecpPrivKeyGen(bz []byte) tmcrypto.PrivKey { func (kb baseKeybase) CreateAccount( keyWriter keyWriter, name, mnemonic, bip39Passphrase, encryptPasswd, hdPath string, algo SigningAlgo, ) (Info, error) { - // create master key and derive first key for keyring derivedPriv, err := kb.options.deriveFunc(mnemonic, bip39Passphrase, hdPath, algo) if err != nil { From 0f4e1ede63c215a40c9aee7b1e2a815c9eb9c69a Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 18:39:21 +0100 Subject: [PATCH 047/148] supported algorithm changed --- crypto/keyring/altkeyring.go | 14 +++++++++----- crypto/keyring/altkeyring_test.go | 32 +++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index c354ecaf508..1fd06bf60e4 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -221,7 +221,7 @@ func (a altKeyring) NewMnemonic(uid string, language Language, algo AltSigningAl return nil, "", ErrUnsupportedLanguage } - if !a.options.supportedAlgos.Contains(algo) { + if !a.isSupportedSigningAlgo(algo) { return nil, "", ErrUnsupportedSigningAlgo } @@ -246,10 +246,10 @@ func (a altKeyring) NewMnemonic(uid string, language Language, algo AltSigningAl } func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase string, hdPath string, algo AltSigningAlgo) (Info, error) { - //if !IsSupportedAlgorithm(a.options.supportedAlgos, algo) { - // return nil, ErrUnsupportedSigningAlgo - //} - // + if !a.isSupportedSigningAlgo(algo) { + return nil, ErrUnsupportedSigningAlgo + } + // create master key and derive first key for keyring derivedPriv, err := algo.DeriveKey(mnemonic, bip39Passphrase, hdPath) if err != nil { @@ -261,6 +261,10 @@ func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase stri return a.writeLocalKey(uid, privKey, SigningAlgo(algo.Name)) } +func (a altKeyring) isSupportedSigningAlgo(algo AltSigningAlgo) bool { + return a.options.supportedAlgos.Contains(algo) +} + func (a altKeyring) Key(uid string) (Info, error) { key := infoKey(uid) diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index ccd019de361..d20211cee23 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -3,6 +3,9 @@ package keyring import ( "testing" + "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/go-bip39" + "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" @@ -50,6 +53,35 @@ func TestAltKeyring_List(t *testing.T) { require.Equal(t, uid1, list[2].GetName()) } +func TestAltKeyring_NewAccount(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + entropy, err := bip39.NewEntropy(defaultEntropySize) + require.NoError(t, err) + + mnemonic, err := bip39.NewMnemonic(entropy) + require.NoError(t, err) + + theUid := "newUid" + + // Fails on creating unsupported SigningAlgo + info, err := keyring.NewAccount(theUid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), unsupportedAlgo) + require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) + + info, err = keyring.NewAccount(theUid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), AltSecp256k1) + require.NoError(t, err) + + require.Equal(t, theUid, info.GetName()) + + list, err := keyring.List() + require.NoError(t, err) + require.Len(t, list, 1) +} + func TestAltKeyring_Get(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) From a9fdd20d646f21596b326d04cf5b84440d568581 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 19:22:15 +0100 Subject: [PATCH 048/148] update al keyring --- crypto/keyring/altkeyring.go | 6 +++--- crypto/keyring/altkeyring_test.go | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 1fd06bf60e4..d80292e103d 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -44,7 +44,7 @@ type Keyring interface { //SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) // SavePubKey stores a public key and returns the persisted Info structure. - SavePubKey(uid string, pubkey tmcrypto.PubKey, algo SigningAlgo) (Info, error) + SavePubKey(uid string, pubkey tmcrypto.PubKey, algo AltSigningAlgo) (Info, error) // SaveMultisig stores, stores, and returns a new multsig (offline) key reference SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) @@ -129,8 +129,8 @@ func (a altKeyring) SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, erro return a.writeMultisigKey(uid, pubkey) } -func (a altKeyring) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo SigningAlgo) (Info, error) { - return a.writeOfflineKey(uid, pubkey, algo) +func (a altKeyring) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo AltSigningAlgo) (Info, error) { + return a.writeOfflineKey(uid, pubkey, algo.Name) } func (a altKeyring) DeleteByAddress(address types.Address) error { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index d20211cee23..1dbdbae7466 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -3,15 +3,14 @@ package keyring import ( "testing" - "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/go-bip39" - "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/multisig" "github.com/cosmos/cosmos-sdk/tests" + "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/go-bip39" ) var unsupportedAlgo = AltSigningAlgo{ @@ -175,10 +174,11 @@ func TestAltKeyring_SavePubKey(t *testing.T) { priv := ed25519.GenPrivKey() pub := priv.PubKey() - info, err := keyring.SavePubKey(key, pub, Secp256k1) + info, err := keyring.SavePubKey(key, pub, AltSecp256k1) require.Nil(t, err) require.Equal(t, pub, info.GetPubKey()) require.Equal(t, key, info.GetName()) + require.Equal(t, AltSecp256k1.Name, info.GetAlgo()) list, err = keyring.List() require.NoError(t, err) From d5ca45e65ab19bbed3ae4ee31ac97bebf2ad840f Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 19:23:18 +0100 Subject: [PATCH 049/148] update options --- crypto/keyring/altkeyring.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index d80292e103d..4dbb5ceebfa 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -109,8 +109,8 @@ func NewAltKeyring( return altKeyring{ db: db, options: altKrOptions{ - supportedAlgos: []AltSigningAlgo{AltSecp256k1}, - supportedAlgosLedger: []AltSigningAlgo{AltSecp256k1}, + supportedAlgos: AltSigningAlgoList{AltSecp256k1}, + supportedAlgosLedger: AltSigningAlgoList{AltSecp256k1}, }, }, nil } From 5c6649531e924df322686dd6fb0c4d1c25b37e13 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 21:02:47 +0100 Subject: [PATCH 050/148] add supported algorithm test and SAveLedgerKey --- crypto/keyring/altkeyring.go | 36 ++++++++++++++++++++++++++----- crypto/keyring/altkeyring_test.go | 20 +++++++++++++++++ 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 4dbb5ceebfa..fae9622895d 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -6,6 +6,9 @@ import ( "sort" "strings" + "github.com/cosmos/cosmos-sdk/crypto" + "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/99designs/keyring" "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/go-bip39" @@ -40,17 +43,14 @@ type Keyring interface { // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo AltSigningAlgo) (Info, error) - //// SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. - //SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) + // SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. + SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, account, index uint32) (Info, error) // SavePubKey stores a public key and returns the persisted Info structure. SavePubKey(uid string, pubkey tmcrypto.PubKey, algo AltSigningAlgo) (Info, error) // SaveMultisig stores, stores, and returns a new multsig (offline) key reference SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) - - //// SupportedAlgosLedger returns a list of signing algorithms supported by the keybase's ledger integration - //SupportedAlgosLedger() []SigningAlgo } // Signer is implemented by key stores that want to provide signing capabilities. @@ -120,6 +120,32 @@ type altKeyring struct { options altKrOptions } +func (a altKeyring) SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, account, index uint32) (Info, error) { + if !a.options.supportedAlgosLedger.Contains(algo) { + return nil, ErrUnsupportedSigningAlgo + } + + coinType := types.GetConfig().GetCoinType() + hdPath := hd.NewFundraiserParams(account, coinType, index) + + priv, _, err := crypto.NewPrivKeyLedgerSecp256k1(*hdPath, hrp) + if err != nil { + return nil, err + } + + return a.writeLedgerKey(uid, priv.PubKey(), *hdPath, algo.Name) +} + +func (a altKeyring) writeLedgerKey(name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo SigningAlgo) (Info, error) { + info := newLedgerInfo(name, pub, path, algo) + err := a.writeInfo(name, info) + if err != nil { + return nil, err + } + + return info, nil +} + type altKrOptions struct { supportedAlgos AltSigningAlgoList supportedAlgosLedger AltSigningAlgoList diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 1dbdbae7466..dea971bf8a1 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -81,6 +81,26 @@ func TestAltKeyring_NewAccount(t *testing.T) { require.Len(t, list, 1) } +func TestAltKeyring_SaveLedgerKey(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + // Test unsupported Algo + i1, err := keyring.SaveLedgerKey("key", unsupportedAlgo, "cosmos", 0, 0) + require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) + + i1, err = keyring.SaveLedgerKey("key", AltSecp256k1, "cosmos", 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()) +} + func TestAltKeyring_Get(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) From cc2b794f4f5acf0ddfc58f1640da15609b85901e Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 27 Mar 2020 21:05:03 +0100 Subject: [PATCH 051/148] fix imports --- crypto/keyring/altkeyring.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index fae9622895d..a9f5cf2ef43 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -6,15 +6,14 @@ import ( "sort" "strings" + "github.com/99designs/keyring" + "github.com/cosmos/cosmos-sdk/crypto" "github.com/cosmos/cosmos-sdk/crypto/keys/hd" - - "github.com/99designs/keyring" "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/go-bip39" tmcrypto "github.com/tendermint/tendermint/crypto" - - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) var ( From a39fd3de47f9ed864e497c2c4da81bc25046145f Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 30 Mar 2020 12:59:21 +0200 Subject: [PATCH 052/148] add signature into keyring --- crypto/keyring/altkeyring.go | 47 ++++++++++++++++++++++++++++++- crypto/keyring/altkeyring_test.go | 19 +++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index a9f5cf2ef43..3c2bbbcbce5 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -6,6 +6,9 @@ import ( "sort" "strings" + "github.com/pkg/errors" + cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" + "github.com/99designs/keyring" "github.com/cosmos/cosmos-sdk/crypto" @@ -50,12 +53,16 @@ type Keyring interface { // SaveMultisig stores, stores, and returns a new multsig (offline) key reference SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) + + Signer } // Signer is implemented by key stores that want to provide signing capabilities. type Signer interface { - // Sign and SignByAddress sign byte messages with a user key. + // Sign sign byte messages with a user key. Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error) + + // SignByAddress sign byte messages with a user key providing the address. SignByAddress(address types.Address, msg []byte) ([]byte, tmcrypto.PubKey, error) } @@ -119,6 +126,44 @@ type altKeyring struct { options altKrOptions } +func (a altKeyring) Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error) { + info, err := a.Key(uid) + if err != nil { + return nil, nil, err + } + + var priv tmcrypto.PrivKey + + switch i := info.(type) { + case localInfo: + if i.PrivKeyArmor == "" { + return nil, nil, fmt.Errorf("private key not available") + } + + priv, err = cryptoAmino.PrivKeyFromBytes([]byte(i.PrivKeyArmor)) + if err != nil { + return nil, nil, err + } + + case ledgerInfo: + return SignWithLedger(info, msg) + + case offlineInfo, multiInfo: + return nil, info.GetPubKey(), 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 (a altKeyring) SignByAddress(address types.Address, msg []byte) ([]byte, tmcrypto.PubKey, error) { + panic("implement me") +} + func (a altKeyring) SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, account, index uint32) (Info, error) { if !a.options.supportedAlgosLedger.Contains(algo) { return nil, ErrUnsupportedSigningAlgo diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index dea971bf8a1..2b2d3f5f40e 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -230,6 +230,25 @@ func TestAltKeyring_SaveMultisig(t *testing.T) { require.Len(t, list, 3) } +func TestAltKeyring_Sign(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "jack" + _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) + require.NoError(t, err) + + msg := []byte("some message") + + sign, key, err := keyring.Sign(uid, msg) + require.NoError(t, err) + + require.True(t, key.VerifyBytes(msg, sign)) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) From 59f9b4dfb0dbc1bbdab875851bad0fe59d96be99 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 30 Mar 2020 13:07:47 +0200 Subject: [PATCH 053/148] add method to sign by address --- crypto/keyring/altkeyring.go | 7 ++++++- crypto/keyring/altkeyring_test.go | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 3c2bbbcbce5..9de2d91c377 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -161,7 +161,12 @@ func (a altKeyring) Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error } func (a altKeyring) SignByAddress(address types.Address, msg []byte) ([]byte, tmcrypto.PubKey, error) { - panic("implement me") + key, err := a.KeyByAddress(address) + if err != nil { + return nil, nil, err + } + + return a.Sign(key.GetName(), msg) } func (a altKeyring) SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, account, index uint32) (Info, error) { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 2b2d3f5f40e..90f31dcc4c5 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -249,6 +249,25 @@ func TestAltKeyring_Sign(t *testing.T) { require.True(t, key.VerifyBytes(msg, sign)) } +func TestAltKeyring_SignByAddress(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "jack" + mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) + require.NoError(t, err) + + msg := []byte("some message") + + sign, key, err := keyring.SignByAddress(mnemonic.GetAddress(), msg) + require.NoError(t, err) + + require.True(t, key.VerifyBytes(msg, sign)) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) From a7c397e06a20b74a2441158f787f243ce649db7d Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 30 Mar 2020 16:23:45 +0200 Subject: [PATCH 054/148] implement import export --- crypto/keyring/altkeyring.go | 92 ++++++++++++++++++++++++++++++- crypto/keyring/altkeyring_test.go | 31 +++++++++++ 2 files changed, 120 insertions(+), 3 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 9de2d91c377..c2a39f033c1 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -6,10 +6,11 @@ import ( "sort" "strings" - "github.com/pkg/errors" - cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" + "github.com/cosmos/cosmos-sdk/crypto/keys/mintkey" "github.com/99designs/keyring" + "github.com/pkg/errors" + cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" "github.com/cosmos/cosmos-sdk/crypto" "github.com/cosmos/cosmos-sdk/crypto/keys/hd" @@ -55,6 +56,9 @@ type Keyring interface { SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) Signer + + Importer + Exporter } // Signer is implemented by key stores that want to provide signing capabilities. @@ -126,6 +130,88 @@ type altKeyring struct { options altKrOptions } +func (a altKeyring) ExportPubKeyArmor(uid string) (string, error) { + panic("implement me") +} + +func (a altKeyring) ExportPubKeyArmorByAddress(address types.Address) (string, error) { + panic("implement me") +} + +func (a altKeyring) ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) { + priv, err := a.ExportPrivateKeyObject(uid) + if err != nil { + return "", err + } + + info, err := a.Key(uid) + if err != nil { + return "", err + } + + return mintkey.EncryptArmorPrivKey(priv, encryptPassphrase, string(info.GetAlgo())), nil +} + +// ExportPrivateKeyObject exports an armored private key object. +func (a altKeyring) ExportPrivateKeyObject(uid string) (tmcrypto.PrivKey, error) { + info, err := a.Key(uid) + if err != nil { + return nil, err + } + + var priv tmcrypto.PrivKey + + switch linfo := info.(type) { + case localInfo: + if linfo.PrivKeyArmor == "" { + err = fmt.Errorf("private key not available") + return nil, err + } + + priv, err = cryptoAmino.PrivKeyFromBytes([]byte(linfo.PrivKeyArmor)) + if err != nil { + return nil, err + } + + case ledgerInfo, offlineInfo, multiInfo: + return nil, errors.New("only works on local private keys") + } + + return priv, nil +} + +func (a altKeyring) ExportPrivKeyArmorByAddress(address types.Address, encryptPassphrase string) (armor string, err error) { + panic("implement me") +} + +func (a altKeyring) ImportPrivKey(uid, armor, passphrase string) error { + if a.hasKey(uid) { + return fmt.Errorf("cannot overwrite key: %s", uid) + } + + privKey, algo, err := mintkey.UnarmorDecryptPrivKey(armor, passphrase) + if err != nil { + return errors.Wrap(err, "failed to decrypt private key") + } + + _, err = a.writeLocalKey(uid, privKey, SigningAlgo(algo)) + if err != nil { + return err + } + + return nil +} + +// HasKey returns whether the key exists in the keyring. +func (a altKeyring) hasKey(name string) bool { + bz, _ := a.Key(name) + return bz != nil +} + +func (a altKeyring) ImportPubKey(uid string, armor string) error { + panic("implement me") +} + func (a altKeyring) Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error) { info, err := a.Key(uid) if err != nil { @@ -333,7 +419,7 @@ func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase stri privKey := algo.PrivKeyGen(derivedPriv) - return a.writeLocalKey(uid, privKey, SigningAlgo(algo.Name)) + return a.writeLocalKey(uid, privKey, algo.Name) } func (a altKeyring) isSupportedSigningAlgo(algo AltSigningAlgo) bool { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 90f31dcc4c5..afbfae139fb 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -1,8 +1,11 @@ package keyring import ( + "fmt" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" @@ -268,6 +271,34 @@ func TestAltKeyring_SignByAddress(t *testing.T) { require.True(t, key.VerifyBytes(msg, sign)) } +func TestAltKeyring_ImportExportPrivKey(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "theId" + _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) + require.NoError(t, err) + + passphrase := "somePass" + armor, err := keyring.ExportPrivKeyArmor(uid, passphrase) + require.NoError(t, err) + + // Should fail importing private key on existing key. + err = keyring.ImportPrivKey(uid, armor, passphrase) + require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", uid)) + + newUid := "theNewId" + // Should fail importing with wrong password + err = keyring.ImportPrivKey(newUid, armor, "wrongPass") + require.EqualError(t, err, "failed to decrypt private key: ciphertext decryption failed") + + err = keyring.ImportPrivKey(newUid, armor, passphrase) + assert.NoError(t, err) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) From dabff2df5ef7f1494b6e6998f47fdbab1bac9755 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 30 Mar 2020 16:32:28 +0200 Subject: [PATCH 055/148] implement the alt keyring --- crypto/keyring/altkeyring.go | 7 ++++++- crypto/keyring/altkeyring_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index c2a39f033c1..e9ed4da4800 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -181,7 +181,12 @@ func (a altKeyring) ExportPrivateKeyObject(uid string) (tmcrypto.PrivKey, error) } func (a altKeyring) ExportPrivKeyArmorByAddress(address types.Address, encryptPassphrase string) (armor string, err error) { - panic("implement me") + byAddress, err := a.KeyByAddress(address) + if err != nil { + return "", err + } + + return a.ExportPrivKeyArmor(byAddress.GetName(), encryptPassphrase) } func (a altKeyring) ImportPrivKey(uid, armor, passphrase string) error { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index afbfae139fb..45aaddb6b4d 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -299,6 +299,34 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { assert.NoError(t, err) } +func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "theId" + mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) + require.NoError(t, err) + + passphrase := "somePass" + armor, err := keyring.ExportPrivKeyArmorByAddress(mnemonic.GetAddress(), passphrase) + require.NoError(t, err) + + // Should fail importing private key on existing key. + err = keyring.ImportPrivKey(uid, armor, passphrase) + require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", uid)) + + newUid := "theNewId" + // Should fail importing with wrong password + err = keyring.ImportPrivKey(newUid, armor, "wrongPass") + require.EqualError(t, err, "failed to decrypt private key: ciphertext decryption failed") + + err = keyring.ImportPrivKey(newUid, armor, passphrase) + assert.NoError(t, err) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) From 639b1caf7aa1e4eb2e5ba1a62e752a79707d7b80 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 30 Mar 2020 16:50:30 +0200 Subject: [PATCH 056/148] finish implementing altKeyring --- crypto/keyring/altkeyring.go | 47 +++++++++++++++++++++++++++---- crypto/keyring/altkeyring_test.go | 46 ++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 5 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index e9ed4da4800..1dde943d236 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -6,14 +6,13 @@ import ( "sort" "strings" - "github.com/cosmos/cosmos-sdk/crypto/keys/mintkey" - "github.com/99designs/keyring" "github.com/pkg/errors" cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" "github.com/cosmos/cosmos-sdk/crypto" "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/crypto/keys/mintkey" "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/go-bip39" @@ -131,11 +130,25 @@ type altKeyring struct { } func (a altKeyring) ExportPubKeyArmor(uid string) (string, error) { - panic("implement me") + bz, err := a.Key(uid) + if err != nil { + return "", err + } + + if bz == nil { + return "", fmt.Errorf("no key to export with name: %s", uid) + } + + return mintkey.ArmorPubKeyBytes(bz.GetPubKey().Bytes(), string(bz.GetAlgo())), nil } func (a altKeyring) ExportPubKeyArmorByAddress(address types.Address) (string, error) { - panic("implement me") + info, err := a.KeyByAddress(address) + if err != nil { + return "", err + } + + return a.ExportPubKeyArmor(info.GetName()) } func (a altKeyring) ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) { @@ -214,7 +227,31 @@ func (a altKeyring) hasKey(name string) bool { } func (a altKeyring) ImportPubKey(uid string, armor string) error { - panic("implement me") + bz, _ := a.Key(uid) + if bz != nil { + pubkey := bz.GetPubKey() + + if len(pubkey.Bytes()) > 0 { + return fmt.Errorf("cannot overwrite data for name: %s", uid) + } + } + + pubBytes, algo, err := mintkey.UnarmorPubKeyBytes(armor) + if err != nil { + return err + } + + pubKey, err := cryptoAmino.PubKeyFromBytes(pubBytes) + if err != nil { + return err + } + + _, err = a.writeOfflineKey(uid, pubKey, SigningAlgo(algo)) + if err != nil { + return err + } + + return nil } func (a altKeyring) Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error) { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 45aaddb6b4d..145e115ff24 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -327,6 +327,52 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { assert.NoError(t, err) } +func TestAltKeyring_ImportExportPubKey(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "theId" + _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) + require.NoError(t, err) + + armor, err := keyring.ExportPubKeyArmor(uid) + require.NoError(t, err) + + // Should fail importing private key on existing key. + err = keyring.ImportPubKey(uid, armor) + require.EqualError(t, err, fmt.Sprintf("cannot overwrite data for name: %s", uid)) + + newUid := "theNewId" + err = keyring.ImportPubKey(newUid, armor) + assert.NoError(t, err) +} + +func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + uid := "theId" + mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) + require.NoError(t, err) + + armor, err := keyring.ExportPubKeyArmorByAddress(mnemonic.GetAddress()) + require.NoError(t, err) + + // Should fail importing private key on existing key. + err = keyring.ImportPubKey(uid, armor) + require.EqualError(t, err, fmt.Sprintf("cannot overwrite data for name: %s", uid)) + + newUid := "theNewId" + err = keyring.ImportPubKey(newUid, armor) + assert.NoError(t, err) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) From 8ad06f9885dd8ed8684d92a49b8326f87e1f9b94 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 30 Mar 2020 16:56:05 +0200 Subject: [PATCH 057/148] refactor thekey --- crypto/keyring/altkeyring_test.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 145e115ff24..24a7ac08c92 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -16,6 +16,8 @@ import ( "github.com/cosmos/go-bip39" ) +const someKey = "theKey" + var unsupportedAlgo = AltSigningAlgo{ Name: "unsupported", DeriveKey: nil, @@ -111,7 +113,7 @@ func TestAltKeyring_Get(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := "theKey" + uid := someKey mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -127,7 +129,7 @@ func TestAltKeyring_KeyByAddress(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := "theKey" + uid := someKey mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -143,7 +145,7 @@ func TestAltKeyring_Delete(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := "theKey" + uid := someKey _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -166,7 +168,7 @@ func TestAltKeyring_DeleteByAddress(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := "theKey" + uid := someKey mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) From 39ab64a81036e246d98b9ebc398061394220d9e4 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 30 Mar 2020 17:05:26 +0200 Subject: [PATCH 058/148] fix the tests --- crypto/keyring/altkeyring_test.go | 47 ++++++++++++++++--------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 24a7ac08c92..0bb58ec7c2f 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -16,7 +16,10 @@ import ( "github.com/cosmos/go-bip39" ) -const someKey = "theKey" +const ( + someKey = "theKey" + theId = "theId" +) var unsupportedAlgo = AltSigningAlgo{ Name: "unsupported", @@ -70,16 +73,16 @@ func TestAltKeyring_NewAccount(t *testing.T) { mnemonic, err := bip39.NewMnemonic(entropy) require.NoError(t, err) - theUid := "newUid" + uid := "newUid" // Fails on creating unsupported SigningAlgo - info, err := keyring.NewAccount(theUid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), unsupportedAlgo) + _, err = keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), unsupportedAlgo) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) - info, err = keyring.NewAccount(theUid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), AltSecp256k1) + info, err := keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), AltSecp256k1) require.NoError(t, err) - require.Equal(t, theUid, info.GetName()) + require.Equal(t, uid, info.GetName()) list, err := keyring.List() require.NoError(t, err) @@ -94,16 +97,16 @@ func TestAltKeyring_SaveLedgerKey(t *testing.T) { require.NoError(t, err) // Test unsupported Algo - i1, err := keyring.SaveLedgerKey("key", unsupportedAlgo, "cosmos", 0, 0) + _, err = keyring.SaveLedgerKey("key", unsupportedAlgo, "cosmos", 0, 0) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) - i1, err = keyring.SaveLedgerKey("key", AltSecp256k1, "cosmos", 0, 0) + info, err := keyring.SaveLedgerKey("key", AltSecp256k1, "cosmos", 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", info.GetName()) } func TestAltKeyring_Get(t *testing.T) { @@ -280,7 +283,7 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := "theId" + uid := theId _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -292,12 +295,12 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { err = keyring.ImportPrivKey(uid, armor, passphrase) require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", uid)) - newUid := "theNewId" + newUID := "theNewId" // Should fail importing with wrong password - err = keyring.ImportPrivKey(newUid, armor, "wrongPass") + err = keyring.ImportPrivKey(newUID, armor, "wrongPass") require.EqualError(t, err, "failed to decrypt private key: ciphertext decryption failed") - err = keyring.ImportPrivKey(newUid, armor, passphrase) + err = keyring.ImportPrivKey(newUID, armor, passphrase) assert.NoError(t, err) } @@ -308,7 +311,7 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := "theId" + uid := theId mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -320,12 +323,12 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { err = keyring.ImportPrivKey(uid, armor, passphrase) require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", uid)) - newUid := "theNewId" + newUID := "theNewId" // Should fail importing with wrong password - err = keyring.ImportPrivKey(newUid, armor, "wrongPass") + err = keyring.ImportPrivKey(newUID, armor, "wrongPass") require.EqualError(t, err, "failed to decrypt private key: ciphertext decryption failed") - err = keyring.ImportPrivKey(newUid, armor, passphrase) + err = keyring.ImportPrivKey(newUID, armor, passphrase) assert.NoError(t, err) } @@ -336,7 +339,7 @@ func TestAltKeyring_ImportExportPubKey(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := "theId" + uid := theId _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -347,8 +350,8 @@ func TestAltKeyring_ImportExportPubKey(t *testing.T) { err = keyring.ImportPubKey(uid, armor) require.EqualError(t, err, fmt.Sprintf("cannot overwrite data for name: %s", uid)) - newUid := "theNewId" - err = keyring.ImportPubKey(newUid, armor) + newUID := "theNewId" + err = keyring.ImportPubKey(newUID, armor) assert.NoError(t, err) } @@ -359,7 +362,7 @@ func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := "theId" + uid := theId mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -370,8 +373,8 @@ func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { err = keyring.ImportPubKey(uid, armor) require.EqualError(t, err, fmt.Sprintf("cannot overwrite data for name: %s", uid)) - newUid := "theNewId" - err = keyring.ImportPubKey(newUid, armor) + newUID := "theNewId" + err = keyring.ImportPubKey(newUID, armor) assert.NoError(t, err) } From ce541b1885411fb2dbdb4a96b9b303ec92ca5f04 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 30 Mar 2020 17:15:36 +0200 Subject: [PATCH 059/148] fixt ci linter errors --- crypto/keyring/altkeyring_test.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 0bb58ec7c2f..9f95cd3fe38 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -18,7 +18,8 @@ import ( const ( someKey = "theKey" - theId = "theId" + theID = "theID" + otherID = "otherID" ) var unsupportedAlgo = AltSigningAlgo{ @@ -283,7 +284,7 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := theId + uid := theID _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -295,7 +296,7 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { err = keyring.ImportPrivKey(uid, armor, passphrase) require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", uid)) - newUID := "theNewId" + newUID := otherID // Should fail importing with wrong password err = keyring.ImportPrivKey(newUID, armor, "wrongPass") require.EqualError(t, err, "failed to decrypt private key: ciphertext decryption failed") @@ -311,7 +312,7 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := theId + uid := theID mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -323,7 +324,7 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { err = keyring.ImportPrivKey(uid, armor, passphrase) require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", uid)) - newUID := "theNewId" + newUID := otherID // Should fail importing with wrong password err = keyring.ImportPrivKey(newUID, armor, "wrongPass") require.EqualError(t, err, "failed to decrypt private key: ciphertext decryption failed") @@ -339,7 +340,7 @@ func TestAltKeyring_ImportExportPubKey(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := theId + uid := theID _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -350,7 +351,7 @@ func TestAltKeyring_ImportExportPubKey(t *testing.T) { err = keyring.ImportPubKey(uid, armor) require.EqualError(t, err, fmt.Sprintf("cannot overwrite data for name: %s", uid)) - newUID := "theNewId" + newUID := otherID err = keyring.ImportPubKey(newUID, armor) assert.NoError(t, err) } @@ -362,7 +363,7 @@ func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - uid := theId + uid := theID mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) require.NoError(t, err) @@ -373,7 +374,7 @@ func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { err = keyring.ImportPubKey(uid, armor) require.EqualError(t, err, fmt.Sprintf("cannot overwrite data for name: %s", uid)) - newUID := "theNewId" + newUID := otherID err = keyring.ImportPubKey(newUID, armor) assert.NoError(t, err) } From e98322a0dc6a0f71fff8657f2f1ab3c7889e0291 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 30 Mar 2020 19:20:10 +0200 Subject: [PATCH 060/148] fix other lint --- crypto/keyring/altkeyring_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 9f95cd3fe38..cf3095a3670 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -199,7 +199,7 @@ func TestAltKeyring_SavePubKey(t *testing.T) { require.NoError(t, err) require.Empty(t, list) - key := "offline" + key := someKey priv := ed25519.GenPrivKey() pub := priv.PubKey() From 04ebcb3bdc8c345032944382bdc51c16fc5d3a6a Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Tue, 31 Mar 2020 17:20:36 +0200 Subject: [PATCH 061/148] Import interface from jonathan's branch --- crypto/keyring/keyring.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index d2b347fcb40..d1ebfa0b6f3 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -44,7 +44,6 @@ var _ Keybase = keyringKeybase{} // Keyring exposes operations on a generic keystore type Keyring interface { - // List all keys. List() ([]Info, error) @@ -52,7 +51,7 @@ type Keyring interface { Key(uid string) (Info, error) KeyByAddress(address types.Address) (Info, error) - // Delete and DeleteByAddress remove keys. + //// Delete and DeleteByAddress remove keys. Delete(uid string) error DeleteByAddress(address types.Address) error @@ -69,23 +68,24 @@ type Keyring interface { SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) // SavePubKey stores a public key and returns the persisted Info structure. - SavePubKey(uid string, pubkey crypto.PubKey, algo SigningAlgo) (Info, error) + SavePubKey(uid string, pubkey tmcrypto.PubKey, algo SigningAlgo) (Info, error) // SaveMultisig stores, stores, and returns a new multsig (offline) key reference - SaveMultisig(uid string, pubkey crypto.PubKey) (Info, error) + SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) - // SupportedAlgos returns a list of signing algorithms supported by the keybase - SupportedAlgos() []SigningAlgo + Signer - // SupportedAlgosLedger returns a list of signing algorithms supported by the keybase's ledger integration - SupportedAlgosLedger() []SigningAlgo + Importer + Exporter } // Signer is implemented by key stores that want to provide signing capabilities. type Signer interface { - // Sign and SignByAddress sign byte messages with a user key. - Sign(uid string, msg []byte) ([]byte, crypto.PubKey, error) - SignByAddress(address types.Address, msg []byte) ([]byte, crypto.PubKey, error) + // Sign sign byte messages with a user key. + Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error) + + // SignByAddress sign byte messages with a user key providing the address. + SignByAddress(address types.Address, msg []byte) ([]byte, tmcrypto.PubKey, error) } // Importer is implemented by key stores that support import of public and private keys. From ec5a6576d8e6c9774ae1fdfa60936cb518b7ca3f Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Tue, 31 Mar 2020 17:28:18 +0200 Subject: [PATCH 062/148] clean up the diff --- client/keys/add.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/keys/add.go b/client/keys/add.go index 8ad6c17351c..1170c714ee3 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -116,10 +116,9 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keybase, inBuf *buf showMnemonic := !viper.GetBool(flagNoBackup) algo := keyring.SigningAlgo(viper.GetString(flagKeyAlgo)) - if algo == "" { + if algo == keyring.SigningAlgo("") { algo = keyring.Secp256k1 } - if !keyring.IsSupportedAlgorithm(kb.SupportedAlgos(), algo) { return keyring.ErrUnsupportedSigningAlgo } From f62f1d2f7af5b86b08e549a00ac1a1db49d7a90a Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Tue, 31 Mar 2020 17:49:56 +0200 Subject: [PATCH 063/148] fix tests after merge --- crypto/keyring/altkeyring.go | 15 ++++---- crypto/keyring/keyring.go | 72 +++--------------------------------- 2 files changed, 13 insertions(+), 74 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 1dde943d236..65878823bc6 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -12,7 +12,6 @@ import ( "github.com/cosmos/cosmos-sdk/crypto" "github.com/cosmos/cosmos-sdk/crypto/keys/hd" - "github.com/cosmos/cosmos-sdk/crypto/keys/mintkey" "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/go-bip39" @@ -139,7 +138,7 @@ func (a altKeyring) ExportPubKeyArmor(uid string) (string, error) { return "", fmt.Errorf("no key to export with name: %s", uid) } - return mintkey.ArmorPubKeyBytes(bz.GetPubKey().Bytes(), string(bz.GetAlgo())), nil + return crypto.ArmorPubKeyBytes(bz.GetPubKey().Bytes(), string(bz.GetAlgo())), nil } func (a altKeyring) ExportPubKeyArmorByAddress(address types.Address) (string, error) { @@ -162,7 +161,7 @@ func (a altKeyring) ExportPrivKeyArmor(uid, encryptPassphrase string) (armor str return "", err } - return mintkey.EncryptArmorPrivKey(priv, encryptPassphrase, string(info.GetAlgo())), nil + return crypto.EncryptArmorPrivKey(priv, encryptPassphrase, string(info.GetAlgo())), nil } // ExportPrivateKeyObject exports an armored private key object. @@ -207,7 +206,7 @@ func (a altKeyring) ImportPrivKey(uid, armor, passphrase string) error { return fmt.Errorf("cannot overwrite key: %s", uid) } - privKey, algo, err := mintkey.UnarmorDecryptPrivKey(armor, passphrase) + privKey, algo, err := crypto.UnarmorDecryptPrivKey(armor, passphrase) if err != nil { return errors.Wrap(err, "failed to decrypt private key") } @@ -236,7 +235,7 @@ func (a altKeyring) ImportPubKey(uid string, armor string) error { } } - pubBytes, algo, err := mintkey.UnarmorPubKeyBytes(armor) + pubBytes, algo, err := crypto.UnarmorPubKeyBytes(armor) if err != nil { return err } @@ -356,7 +355,7 @@ func (a altKeyring) Delete(uid string) error { return err } - err = a.db.Remove(addrKeyAsString(info.GetAddress())) + err = a.db.Remove(addrHexKeyAsString(info.GetAddress())) if err != nil { return err } @@ -370,7 +369,7 @@ func (a altKeyring) Delete(uid string) error { } func (a altKeyring) KeyByAddress(address types.Address) (Info, error) { - ik, err := a.db.Get(addrKeyAsString(address)) + ik, err := a.db.Get(addrHexKeyAsString(address)) if err != nil { return nil, err } @@ -510,7 +509,7 @@ func (a altKeyring) writeInfo(name string, info Info) error { } err = a.db.Set(keyring.Item{ - Key: addrKeyAsString(info.GetAddress()), + Key: addrHexKeyAsString(info.GetAddress()), Data: key, }) if err != nil { diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 620c91269f9..d9aca87d4b4 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -41,70 +41,6 @@ const ( var _ Keybase = keyringKeybase{} -// Keyring exposes operations on a generic keystore -type Keyring interface { - - // List all keys. - List() ([]Info, error) - - // Key and KeyByAddress return keys by uid and address respectively. - Key(uid string) (Info, error) - KeyByAddress(address types.Address) (Info, error) - - // Delete and DeleteByAddress remove keys. - Delete(uid string) error - DeleteByAddress(address types.Address) error - - // NewMnemonic generates a new mnemonic, derives a hierarchical deterministic - // key from that, and persists it to storage. Returns the generated mnemonic and the key - // Info. It returns an error if it fails to generate a key for the given algo type, or if - // another key is already stored under the same name. - NewMnemonic(uid string, language Language, algo SigningAlgo) (Info, string, error) - - // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. - NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SigningAlgo) (Info, error) - - // SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. - SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) - - // SavePubKey stores a public key and returns the persisted Info structure. - SavePubKey(uid string, pubkey tmcrypto.PubKey, algo SigningAlgo) (Info, error) - - // SaveMultisig stores, stores, and returns a new multsig (offline) key reference - SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) - - Signer - - Importer - Exporter -} - -// Signer is implemented by key stores that want to provide signing capabilities. -type Signer interface { - // Sign sign byte messages with a user key. - Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error) - - // SignByAddress sign byte messages with a user key providing the address. - SignByAddress(address types.Address, msg []byte) ([]byte, tmcrypto.PubKey, error) -} - -// Importer is implemented by key stores that support import of public and private keys. -type Importer interface { - ImportPrivKey(uid, armor, passphrase string) error - ImportPubKey(uid string, armor string) error -} - -// Exporter is implemented by key stores that support export of public and private keys. -type Exporter interface { - // Export public key - ExportPubKeyArmor(uid string) (string, error) - ExportPubKeyArmorByAddress(address types.Address) (string, error) - // 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. - ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) - ExportPrivKeyArmorByAddress(address types.Address, encryptPassphrase string) (armor string, err error) -} - // keyringKeybase implements the Keybase interface by using the Keyring library // for account key persistence. type keyringKeybase struct { @@ -650,6 +586,10 @@ func newRealPrompt(dir string, buf io.Reader) func(string) (string, error) { } } -func addrHexKey(address types.AccAddress) []byte { - return []byte(fmt.Sprintf("%s.%s", hex.EncodeToString(address.Bytes()), addressSuffix)) +func addrHexKey(address types.Address) []byte { + return []byte(addrHexKeyAsString(address)) +} + +func addrHexKeyAsString(address types.Address) string { + return fmt.Sprintf("%s.%s", hex.EncodeToString(address.Bytes()), addressSuffix) } From fbf08c28830fdd8eaa94f143427c8939d8457118 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Tue, 31 Mar 2020 18:02:58 +0200 Subject: [PATCH 064/148] add interface for signing algo --- crypto/keyring/alt_signing_algorithms.go | 27 ++++++++++++++----- crypto/keyring/alt_signing_algorithms_test.go | 21 +++++++++++---- crypto/keyring/altkeyring.go | 10 +++---- crypto/keyring/altkeyring_test.go | 13 +++------ 4 files changed, 46 insertions(+), 25 deletions(-) diff --git a/crypto/keyring/alt_signing_algorithms.go b/crypto/keyring/alt_signing_algorithms.go index 9c7d22072c6..91a2f2e9d95 100644 --- a/crypto/keyring/alt_signing_algorithms.go +++ b/crypto/keyring/alt_signing_algorithms.go @@ -2,25 +2,40 @@ package keyring import "github.com/tendermint/tendermint/crypto" -type AltSigningAlgo struct { - Name SigningAlgo - DeriveKey AltDeriveKeyFunc - PrivKeyGen AltPrivKeyGenFunc +type AltSigningAlgo interface { + Name() SigningAlgo + DeriveKey() AltDeriveKeyFunc + PrivKeyGen() AltPrivKeyGenFunc } type AltDeriveKeyFunc func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) type AltPrivKeyGenFunc func(bz []byte) crypto.PrivKey +type secp256k1Algo struct { +} + +func (s secp256k1Algo) Name() SigningAlgo { + return Secp256k1 +} + +func (s secp256k1Algo) DeriveKey() AltDeriveKeyFunc { + return SecpDeriveKey +} + +func (s secp256k1Algo) PrivKeyGen() AltPrivKeyGenFunc { + return SecpPrivKeyGen +} + var ( // Secp256k1 uses the Bitcoin secp256k1 ECDSA parameters. - AltSecp256k1 = AltSigningAlgo{Name: Secp256k1, DeriveKey: SecpDeriveKey, PrivKeyGen: SecpPrivKeyGen} + AltSecp256k1 = secp256k1Algo{} ) type AltSigningAlgoList []AltSigningAlgo func (l AltSigningAlgoList) Contains(algo AltSigningAlgo) bool { for _, cAlgo := range l { - if cAlgo.Name == algo.Name { + if cAlgo.Name() == algo.Name() { return true } } diff --git a/crypto/keyring/alt_signing_algorithms_test.go b/crypto/keyring/alt_signing_algorithms_test.go index 91c2e96cf67..f56e8078284 100644 --- a/crypto/keyring/alt_signing_algorithms_test.go +++ b/crypto/keyring/alt_signing_algorithms_test.go @@ -11,10 +11,21 @@ func TestAltSigningAlgoList_Contains(t *testing.T) { AltSecp256k1, } - notSupportedAlgo := AltSigningAlgo{ - Name: "anotherAlgo", - DeriveKey: nil, - } assert.True(t, list.Contains(AltSecp256k1)) - assert.False(t, list.Contains(notSupportedAlgo)) + assert.False(t, list.Contains(notSupportedAlgo{})) +} + +type notSupportedAlgo struct { +} + +func (n notSupportedAlgo) Name() SigningAlgo { + return "notSupported" +} + +func (n notSupportedAlgo) DeriveKey() AltDeriveKeyFunc { + panic("implement me") +} + +func (n notSupportedAlgo) PrivKeyGen() AltPrivKeyGenFunc { + panic("implement me") } diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 65878823bc6..70820657a58 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -309,7 +309,7 @@ func (a altKeyring) SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, a return nil, err } - return a.writeLedgerKey(uid, priv.PubKey(), *hdPath, algo.Name) + return a.writeLedgerKey(uid, priv.PubKey(), *hdPath, algo.Name()) } func (a altKeyring) writeLedgerKey(name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo SigningAlgo) (Info, error) { @@ -332,7 +332,7 @@ func (a altKeyring) SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, erro } func (a altKeyring) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo AltSigningAlgo) (Info, error) { - return a.writeOfflineKey(uid, pubkey, algo.Name) + return a.writeOfflineKey(uid, pubkey, algo.Name()) } func (a altKeyring) DeleteByAddress(address types.Address) error { @@ -453,14 +453,14 @@ func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase stri } // create master key and derive first key for keyring - derivedPriv, err := algo.DeriveKey(mnemonic, bip39Passphrase, hdPath) + derivedPriv, err := algo.DeriveKey()(mnemonic, bip39Passphrase, hdPath) if err != nil { return nil, err } - privKey := algo.PrivKeyGen(derivedPriv) + privKey := algo.PrivKeyGen()(derivedPriv) - return a.writeLocalKey(uid, privKey, algo.Name) + return a.writeLocalKey(uid, privKey, algo.Name()) } func (a altKeyring) isSupportedSigningAlgo(algo AltSigningAlgo) bool { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index cf3095a3670..5a34d462199 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -22,11 +22,6 @@ const ( otherID = "otherID" ) -var unsupportedAlgo = AltSigningAlgo{ - Name: "unsupported", - DeriveKey: nil, -} - func TestAltKeyring_List(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) @@ -39,7 +34,7 @@ func TestAltKeyring_List(t *testing.T) { require.Empty(t, list) // Fails on creating unsupported SigningAlgo - _, _, err = keyring.NewMnemonic("failing", English, unsupportedAlgo) + _, _, err = keyring.NewMnemonic("failing", English, notSupportedAlgo{}) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) // Create 3 keys @@ -77,7 +72,7 @@ func TestAltKeyring_NewAccount(t *testing.T) { uid := "newUid" // Fails on creating unsupported SigningAlgo - _, err = keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), unsupportedAlgo) + _, err = keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), notSupportedAlgo{}) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) info, err := keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), AltSecp256k1) @@ -98,7 +93,7 @@ func TestAltKeyring_SaveLedgerKey(t *testing.T) { require.NoError(t, err) // Test unsupported Algo - _, err = keyring.SaveLedgerKey("key", unsupportedAlgo, "cosmos", 0, 0) + _, err = keyring.SaveLedgerKey("key", notSupportedAlgo{}, "cosmos", 0, 0) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) info, err := keyring.SaveLedgerKey("key", AltSecp256k1, "cosmos", 0, 0) @@ -207,7 +202,7 @@ func TestAltKeyring_SavePubKey(t *testing.T) { require.Nil(t, err) require.Equal(t, pub, info.GetPubKey()) require.Equal(t, key, info.GetName()) - require.Equal(t, AltSecp256k1.Name, info.GetAlgo()) + require.Equal(t, AltSecp256k1.Name(), info.GetAlgo()) list, err = keyring.List() require.NoError(t, err) From 54f27e11e924ab1f5f90175f245d9b04c3bf83f0 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Tue, 31 Mar 2020 18:39:31 +0200 Subject: [PATCH 065/148] add option to provide signingalgos and testse --- crypto/keyring/alt_signing_algorithms_test.go | 4 +-- crypto/keyring/altkeyring.go | 19 +++++++++--- crypto/keyring/altkeyring_test.go | 31 +++++++++++++++++++ 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/crypto/keyring/alt_signing_algorithms_test.go b/crypto/keyring/alt_signing_algorithms_test.go index f56e8078284..2db5545e2bc 100644 --- a/crypto/keyring/alt_signing_algorithms_test.go +++ b/crypto/keyring/alt_signing_algorithms_test.go @@ -23,9 +23,9 @@ func (n notSupportedAlgo) Name() SigningAlgo { } func (n notSupportedAlgo) DeriveKey() AltDeriveKeyFunc { - panic("implement me") + return SecpDeriveKey } func (n notSupportedAlgo) PrivKeyGen() AltPrivKeyGenFunc { - panic("implement me") + return SecpPrivKeyGen } diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 70820657a58..fbe35f7d6e5 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -85,11 +85,13 @@ type Exporter interface { ExportPrivKeyArmorByAddress(address types.Address, encryptPassphrase string) (armor string, err error) } +type AltKeyringOption func(options *altKrOptions) + // NewKeyring creates a new instance of a keyring. Keybase // options can be applied when generating this new Keybase. // Available backends are "os", "file", "kwallet", "pass", "test". func NewAltKeyring( - appName, backend, rootDir string, userInput io.Reader, + appName, backend, rootDir string, userInput io.Reader, opts ...AltKeyringOption, ) (Keyring, error) { var db keyring.Keyring @@ -114,12 +116,19 @@ func NewAltKeyring( return nil, err } + // Default options for keybase + options := altKrOptions{ + supportedAlgos: AltSigningAlgoList{AltSecp256k1}, + supportedAlgosLedger: AltSigningAlgoList{AltSecp256k1}, + } + + for _, optionFn := range opts { + optionFn(&options) + } + return altKeyring{ db: db, - options: altKrOptions{ - supportedAlgos: AltSigningAlgoList{AltSecp256k1}, - supportedAlgosLedger: AltSigningAlgoList{AltSecp256k1}, - }, + options: options, }, nil } diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 5a34d462199..c113f2f8da4 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -374,6 +374,37 @@ func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { assert.NoError(t, err) } +func TestAltKeyring_ConstructorSupportedAlgos(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + // should fail when using unsupported signing algorythm. + _, _, err = keyring.NewMnemonic("test", English, notSupportedAlgo{}) + require.EqualError(t, err, "unsupported signing algo") + + // but works with default signing algo. + _, _, err = keyring.NewMnemonic("test", English, AltSecp256k1) + require.NoError(t, err) + + // but we can create a new keybase with our provided algos. + dir2, clean2 := tests.NewTestCaseDir(t) + t.Cleanup(clean2) + + keyring2, err := NewAltKeyring(t.Name(), BackendTest, dir2, nil, func(options *altKrOptions) { + options.supportedAlgos = AltSigningAlgoList{ + notSupportedAlgo{}, + } + }) + require.NoError(t, err) + + // now this new keyring does not fail when signing with provided algo + _, _, err = keyring2.NewMnemonic("test", English, notSupportedAlgo{}) + require.NoError(t, err) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) From dbeea7026ac88ccd495b0dcd81a4d2f5cc88b5c7 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Tue, 31 Mar 2020 20:18:57 +0200 Subject: [PATCH 066/148] change Name to String in AltSigningAlgo --- crypto/keyring/alt_signing_algorithms.go | 14 +++++++++----- crypto/keyring/alt_signing_algorithms_test.go | 2 +- crypto/keyring/altkeyring.go | 8 ++++---- crypto/keyring/altkeyring_test.go | 2 +- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/crypto/keyring/alt_signing_algorithms.go b/crypto/keyring/alt_signing_algorithms.go index 91a2f2e9d95..c37a26d8f7e 100644 --- a/crypto/keyring/alt_signing_algorithms.go +++ b/crypto/keyring/alt_signing_algorithms.go @@ -1,9 +1,13 @@ package keyring -import "github.com/tendermint/tendermint/crypto" +import ( + "fmt" + + "github.com/tendermint/tendermint/crypto" +) type AltSigningAlgo interface { - Name() SigningAlgo + fmt.Stringer DeriveKey() AltDeriveKeyFunc PrivKeyGen() AltPrivKeyGenFunc } @@ -14,8 +18,8 @@ type AltPrivKeyGenFunc func(bz []byte) crypto.PrivKey type secp256k1Algo struct { } -func (s secp256k1Algo) Name() SigningAlgo { - return Secp256k1 +func (s secp256k1Algo) String() string { + return string(Secp256k1) } func (s secp256k1Algo) DeriveKey() AltDeriveKeyFunc { @@ -35,7 +39,7 @@ type AltSigningAlgoList []AltSigningAlgo func (l AltSigningAlgoList) Contains(algo AltSigningAlgo) bool { for _, cAlgo := range l { - if cAlgo.Name() == algo.Name() { + if cAlgo.String() == algo.String() { return true } } diff --git a/crypto/keyring/alt_signing_algorithms_test.go b/crypto/keyring/alt_signing_algorithms_test.go index 2db5545e2bc..f86e09e9148 100644 --- a/crypto/keyring/alt_signing_algorithms_test.go +++ b/crypto/keyring/alt_signing_algorithms_test.go @@ -18,7 +18,7 @@ func TestAltSigningAlgoList_Contains(t *testing.T) { type notSupportedAlgo struct { } -func (n notSupportedAlgo) Name() SigningAlgo { +func (n notSupportedAlgo) String() string { return "notSupported" } diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index fbe35f7d6e5..445e23ce39a 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -127,7 +127,7 @@ func NewAltKeyring( } return altKeyring{ - db: db, + db: db, options: options, }, nil } @@ -318,7 +318,7 @@ func (a altKeyring) SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, a return nil, err } - return a.writeLedgerKey(uid, priv.PubKey(), *hdPath, algo.Name()) + return a.writeLedgerKey(uid, priv.PubKey(), *hdPath, SigningAlgo(algo.String())) } func (a altKeyring) writeLedgerKey(name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo SigningAlgo) (Info, error) { @@ -341,7 +341,7 @@ func (a altKeyring) SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, erro } func (a altKeyring) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo AltSigningAlgo) (Info, error) { - return a.writeOfflineKey(uid, pubkey, algo.Name()) + return a.writeOfflineKey(uid, pubkey, SigningAlgo(algo.String())) } func (a altKeyring) DeleteByAddress(address types.Address) error { @@ -469,7 +469,7 @@ func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase stri privKey := algo.PrivKeyGen()(derivedPriv) - return a.writeLocalKey(uid, privKey, algo.Name()) + return a.writeLocalKey(uid, privKey, SigningAlgo(algo.String())) } func (a altKeyring) isSupportedSigningAlgo(algo AltSigningAlgo) bool { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index c113f2f8da4..6760d1add71 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -202,7 +202,7 @@ func TestAltKeyring_SavePubKey(t *testing.T) { require.Nil(t, err) require.Equal(t, pub, info.GetPubKey()) require.Equal(t, key, info.GetName()) - require.Equal(t, AltSecp256k1.Name(), info.GetAlgo()) + require.Equal(t, SigningAlgo(AltSecp256k1.String()), info.GetAlgo()) list, err = keyring.List() require.NoError(t, err) From 0f73f7428c22ebb065dd60f24c4d903a09673d45 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Tue, 31 Mar 2020 20:38:28 +0200 Subject: [PATCH 067/148] Revert "change Name to String in AltSigningAlgo" This reverts commit dbeea7026ac88ccd495b0dcd81a4d2f5cc88b5c7. --- crypto/keyring/alt_signing_algorithms.go | 14 +++++--------- crypto/keyring/alt_signing_algorithms_test.go | 2 +- crypto/keyring/altkeyring.go | 8 ++++---- crypto/keyring/altkeyring_test.go | 2 +- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/crypto/keyring/alt_signing_algorithms.go b/crypto/keyring/alt_signing_algorithms.go index c37a26d8f7e..91a2f2e9d95 100644 --- a/crypto/keyring/alt_signing_algorithms.go +++ b/crypto/keyring/alt_signing_algorithms.go @@ -1,13 +1,9 @@ package keyring -import ( - "fmt" - - "github.com/tendermint/tendermint/crypto" -) +import "github.com/tendermint/tendermint/crypto" type AltSigningAlgo interface { - fmt.Stringer + Name() SigningAlgo DeriveKey() AltDeriveKeyFunc PrivKeyGen() AltPrivKeyGenFunc } @@ -18,8 +14,8 @@ type AltPrivKeyGenFunc func(bz []byte) crypto.PrivKey type secp256k1Algo struct { } -func (s secp256k1Algo) String() string { - return string(Secp256k1) +func (s secp256k1Algo) Name() SigningAlgo { + return Secp256k1 } func (s secp256k1Algo) DeriveKey() AltDeriveKeyFunc { @@ -39,7 +35,7 @@ type AltSigningAlgoList []AltSigningAlgo func (l AltSigningAlgoList) Contains(algo AltSigningAlgo) bool { for _, cAlgo := range l { - if cAlgo.String() == algo.String() { + if cAlgo.Name() == algo.Name() { return true } } diff --git a/crypto/keyring/alt_signing_algorithms_test.go b/crypto/keyring/alt_signing_algorithms_test.go index f86e09e9148..2db5545e2bc 100644 --- a/crypto/keyring/alt_signing_algorithms_test.go +++ b/crypto/keyring/alt_signing_algorithms_test.go @@ -18,7 +18,7 @@ func TestAltSigningAlgoList_Contains(t *testing.T) { type notSupportedAlgo struct { } -func (n notSupportedAlgo) String() string { +func (n notSupportedAlgo) Name() SigningAlgo { return "notSupported" } diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 445e23ce39a..fbe35f7d6e5 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -127,7 +127,7 @@ func NewAltKeyring( } return altKeyring{ - db: db, + db: db, options: options, }, nil } @@ -318,7 +318,7 @@ func (a altKeyring) SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, a return nil, err } - return a.writeLedgerKey(uid, priv.PubKey(), *hdPath, SigningAlgo(algo.String())) + return a.writeLedgerKey(uid, priv.PubKey(), *hdPath, algo.Name()) } func (a altKeyring) writeLedgerKey(name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo SigningAlgo) (Info, error) { @@ -341,7 +341,7 @@ func (a altKeyring) SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, erro } func (a altKeyring) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo AltSigningAlgo) (Info, error) { - return a.writeOfflineKey(uid, pubkey, SigningAlgo(algo.String())) + return a.writeOfflineKey(uid, pubkey, algo.Name()) } func (a altKeyring) DeleteByAddress(address types.Address) error { @@ -469,7 +469,7 @@ func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase stri privKey := algo.PrivKeyGen()(derivedPriv) - return a.writeLocalKey(uid, privKey, SigningAlgo(algo.String())) + return a.writeLocalKey(uid, privKey, algo.Name()) } func (a altKeyring) isSupportedSigningAlgo(algo AltSigningAlgo) bool { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 6760d1add71..c113f2f8da4 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -202,7 +202,7 @@ func TestAltKeyring_SavePubKey(t *testing.T) { require.Nil(t, err) require.Equal(t, pub, info.GetPubKey()) require.Equal(t, key, info.GetName()) - require.Equal(t, SigningAlgo(AltSecp256k1.String()), info.GetAlgo()) + require.Equal(t, AltSecp256k1.Name(), info.GetAlgo()) list, err = keyring.List() require.NoError(t, err) From b06b3ec8415d1fdda56734f6acb709daa35b9a3c Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Wed, 1 Apr 2020 15:37:29 +0200 Subject: [PATCH 068/148] Update crypto/keyring/altkeyring.go Co-Authored-By: Bot from GolangCI <42910462+golangcibot@users.noreply.github.com> --- crypto/keyring/altkeyring.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index fbe35f7d6e5..7730628bbe7 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -127,7 +127,7 @@ func NewAltKeyring( } return altKeyring{ - db: db, + db: db, options: options, }, nil } From 5bb0cbd19e6f11bd5d84ba1adc7e3a5b6cf20b54 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Wed, 1 Apr 2020 18:34:05 +0200 Subject: [PATCH 069/148] Rename old SigningAlgo Must be kept for backward compatibility --- crypto/keyring/alt_signing_algorithms.go | 4 ++-- crypto/keyring/alt_signing_algorithms_test.go | 2 +- crypto/keyring/altkeyring.go | 10 ++++---- crypto/keyring/altkeyring_test.go | 4 ++-- crypto/keyring/base_keybase.go | 24 +++++++++---------- crypto/keyring/info.go | 22 ++++++++--------- crypto/keyring/keybase.go | 12 +++++----- crypto/keyring/keyring.go | 18 +++++++------- crypto/keyring/keyring_test.go | 14 +++++------ crypto/keyring/options.go | 8 +++---- crypto/keyring/signing_algorithms.go | 14 +++++------ crypto/keyring/types.go | 4 ++-- 12 files changed, 68 insertions(+), 68 deletions(-) diff --git a/crypto/keyring/alt_signing_algorithms.go b/crypto/keyring/alt_signing_algorithms.go index 91a2f2e9d95..69b78cba811 100644 --- a/crypto/keyring/alt_signing_algorithms.go +++ b/crypto/keyring/alt_signing_algorithms.go @@ -3,7 +3,7 @@ package keyring import "github.com/tendermint/tendermint/crypto" type AltSigningAlgo interface { - Name() SigningAlgo + Name() pubKeyType DeriveKey() AltDeriveKeyFunc PrivKeyGen() AltPrivKeyGenFunc } @@ -14,7 +14,7 @@ type AltPrivKeyGenFunc func(bz []byte) crypto.PrivKey type secp256k1Algo struct { } -func (s secp256k1Algo) Name() SigningAlgo { +func (s secp256k1Algo) Name() pubKeyType { return Secp256k1 } diff --git a/crypto/keyring/alt_signing_algorithms_test.go b/crypto/keyring/alt_signing_algorithms_test.go index 2db5545e2bc..f210538fe50 100644 --- a/crypto/keyring/alt_signing_algorithms_test.go +++ b/crypto/keyring/alt_signing_algorithms_test.go @@ -18,7 +18,7 @@ func TestAltSigningAlgoList_Contains(t *testing.T) { type notSupportedAlgo struct { } -func (n notSupportedAlgo) Name() SigningAlgo { +func (n notSupportedAlgo) Name() pubKeyType { return "notSupported" } diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 7730628bbe7..ef3cff06252 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -220,7 +220,7 @@ func (a altKeyring) ImportPrivKey(uid, armor, passphrase string) error { return errors.Wrap(err, "failed to decrypt private key") } - _, err = a.writeLocalKey(uid, privKey, SigningAlgo(algo)) + _, err = a.writeLocalKey(uid, privKey, pubKeyType(algo)) if err != nil { return err } @@ -254,7 +254,7 @@ func (a altKeyring) ImportPubKey(uid string, armor string) error { return err } - _, err = a.writeOfflineKey(uid, pubKey, SigningAlgo(algo)) + _, err = a.writeOfflineKey(uid, pubKey, pubKeyType(algo)) if err != nil { return err } @@ -321,7 +321,7 @@ func (a altKeyring) SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, a return a.writeLedgerKey(uid, priv.PubKey(), *hdPath, algo.Name()) } -func (a altKeyring) writeLedgerKey(name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo SigningAlgo) (Info, error) { +func (a altKeyring) writeLedgerKey(name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo pubKeyType) (Info, error) { info := newLedgerInfo(name, pub, path, algo) err := a.writeInfo(name, info) if err != nil { @@ -491,7 +491,7 @@ func (a altKeyring) Key(uid string) (Info, error) { return unmarshalInfo(bs.Data) } -func (a altKeyring) writeLocalKey(name string, priv tmcrypto.PrivKey, algo SigningAlgo) (Info, error) { +func (a altKeyring) writeLocalKey(name string, priv tmcrypto.PrivKey, algo pubKeyType) (Info, error) { // encrypt private key using keyring pub := priv.PubKey() @@ -528,7 +528,7 @@ func (a altKeyring) writeInfo(name string, info Info) error { return nil } -func (a altKeyring) writeOfflineKey(name string, pub tmcrypto.PubKey, algo SigningAlgo) (Info, error) { +func (a altKeyring) writeOfflineKey(name string, pub tmcrypto.PubKey, algo pubKeyType) (Info, error) { info := newOfflineInfo(name, pub, algo) err := a.writeInfo(name, info) if err != nil { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index c113f2f8da4..8178fa0f7bd 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -33,7 +33,7 @@ func TestAltKeyring_List(t *testing.T) { require.NoError(t, err) require.Empty(t, list) - // Fails on creating unsupported SigningAlgo + // Fails on creating unsupported pubKeyType _, _, err = keyring.NewMnemonic("failing", English, notSupportedAlgo{}) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) @@ -71,7 +71,7 @@ func TestAltKeyring_NewAccount(t *testing.T) { uid := "newUid" - // Fails on creating unsupported SigningAlgo + // Fails on creating unsupported pubKeyType _, err = keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), notSupportedAlgo{}) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) diff --git a/crypto/keyring/base_keybase.go b/crypto/keyring/base_keybase.go index 0bdddd321a2..e1d5b300c68 100644 --- a/crypto/keyring/base_keybase.go +++ b/crypto/keyring/base_keybase.go @@ -25,7 +25,7 @@ type ( } writeLocalKeyer interface { - writeLocalKey(name string, priv tmcrypto.PrivKey, algo SigningAlgo) Info + writeLocalKey(name string, priv tmcrypto.PrivKey, algo pubKeyType) Info } infoWriter interface { @@ -41,8 +41,8 @@ func newBaseKeybase(optionsFns ...KeybaseOption) baseKeybase { options := kbOptions{ keygenFunc: StdPrivKeyGen, deriveFunc: StdDeriveKey, - supportedAlgos: []SigningAlgo{Secp256k1}, - supportedAlgosLedger: []SigningAlgo{Secp256k1}, + supportedAlgos: []pubKeyType{Secp256k1}, + supportedAlgosLedger: []pubKeyType{Secp256k1}, } for _, optionFn := range optionsFns { @@ -54,7 +54,7 @@ func newBaseKeybase(optionsFns ...KeybaseOption) baseKeybase { // StdPrivKeyGen is the default PrivKeyGen function in the keybase. // For now, it only supports Secp256k1 -func StdPrivKeyGen(bz []byte, algo SigningAlgo) (tmcrypto.PrivKey, error) { +func StdPrivKeyGen(bz []byte, algo pubKeyType) (tmcrypto.PrivKey, error) { if algo == Secp256k1 { return SecpPrivKeyGen(bz), nil } @@ -70,7 +70,7 @@ func SecpPrivKeyGen(bz []byte) tmcrypto.PrivKey { // CreateAccount creates an account Info object. func (kb baseKeybase) CreateAccount( - keyWriter keyWriter, name, mnemonic, bip39Passphrase, encryptPasswd, hdPath string, algo SigningAlgo, + keyWriter keyWriter, name, mnemonic, bip39Passphrase, encryptPasswd, hdPath string, algo pubKeyType, ) (Info, error) { // create master key and derive first key for keyring derivedPriv, err := kb.options.deriveFunc(mnemonic, bip39Passphrase, hdPath, algo) @@ -97,7 +97,7 @@ func (kb baseKeybase) CreateAccount( // CreateLedger creates a new reference to a Ledger key pair. It returns a public // key and a derivation path. It returns an error if the device could not be queried. func (kb baseKeybase) CreateLedger( - w infoWriter, name string, algo SigningAlgo, hrp string, account, index uint32, + w infoWriter, name string, algo pubKeyType, hrp string, account, index uint32, ) (Info, error) { if !IsSupportedAlgorithm(kb.SupportedAlgosLedger(), algo) { @@ -117,7 +117,7 @@ func (kb baseKeybase) CreateLedger( // CreateMnemonic generates a new key with the given algorithm and language pair. func (kb baseKeybase) CreateMnemonic( - keyWriter keyWriter, name string, language Language, passwd string, algo SigningAlgo, + keyWriter keyWriter, name string, language Language, passwd string, algo pubKeyType, ) (info Info, mnemonic string, err error) { if language != English { @@ -148,13 +148,13 @@ func (kb baseKeybase) CreateMnemonic( return info, mnemonic, err } -func (kb baseKeybase) writeLedgerKey(w infoWriter, name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo SigningAlgo) Info { +func (kb baseKeybase) writeLedgerKey(w infoWriter, name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo pubKeyType) Info { info := newLedgerInfo(name, pub, path, algo) w.writeInfo(name, info) return info } -func (kb baseKeybase) writeOfflineKey(w infoWriter, name string, pub tmcrypto.PubKey, algo SigningAlgo) Info { +func (kb baseKeybase) writeOfflineKey(w infoWriter, name string, pub tmcrypto.PubKey, algo pubKeyType) Info { info := newOfflineInfo(name, pub, algo) w.writeInfo(name, info) return info @@ -168,7 +168,7 @@ func (kb baseKeybase) writeMultisigKey(w infoWriter, name string, pub tmcrypto.P // StdDeriveKey is the default DeriveKey function in the keybase. // For now, it only supports Secp256k1 -func StdDeriveKey(mnemonic string, bip39Passphrase, hdPath string, algo SigningAlgo) ([]byte, error) { +func StdDeriveKey(mnemonic string, bip39Passphrase, hdPath string, algo pubKeyType) ([]byte, error) { if algo == Secp256k1 { return SecpDeriveKey(mnemonic, bip39Passphrase, hdPath) } @@ -196,12 +196,12 @@ func CreateHDPath(account uint32, index uint32) *hd.BIP44Params { } // SupportedAlgos returns a list of supported signing algorithms. -func (kb baseKeybase) SupportedAlgos() []SigningAlgo { +func (kb baseKeybase) SupportedAlgos() []pubKeyType { return kb.options.supportedAlgos } // SupportedAlgosLedger returns a list of supported ledger signing algorithms. -func (kb baseKeybase) SupportedAlgosLedger() []SigningAlgo { +func (kb baseKeybase) SupportedAlgosLedger() []pubKeyType { return kb.options.supportedAlgosLedger } diff --git a/crypto/keyring/info.go b/crypto/keyring/info.go index b9df095a973..4f41b3e1a03 100644 --- a/crypto/keyring/info.go +++ b/crypto/keyring/info.go @@ -23,7 +23,7 @@ type Info interface { // Bip44 Path GetPath() (*hd.BIP44Params, error) // Algo - GetAlgo() SigningAlgo + GetAlgo() pubKeyType } var ( @@ -39,10 +39,10 @@ type localInfo struct { Name string `json:"name"` PubKey crypto.PubKey `json:"pubkey"` PrivKeyArmor string `json:"privkey.armor"` - Algo SigningAlgo `json:"algo"` + Algo pubKeyType `json:"algo"` } -func newLocalInfo(name string, pub crypto.PubKey, privArmor string, algo SigningAlgo) Info { +func newLocalInfo(name string, pub crypto.PubKey, privArmor string, algo pubKeyType) Info { return &localInfo{ Name: name, PubKey: pub, @@ -72,7 +72,7 @@ func (i localInfo) GetAddress() types.AccAddress { } // GetType implements Info interface -func (i localInfo) GetAlgo() SigningAlgo { +func (i localInfo) GetAlgo() pubKeyType { return i.Algo } @@ -87,10 +87,10 @@ type ledgerInfo struct { Name string `json:"name"` PubKey crypto.PubKey `json:"pubkey"` Path hd.BIP44Params `json:"path"` - Algo SigningAlgo `json:"algo"` + Algo pubKeyType `json:"algo"` } -func newLedgerInfo(name string, pub crypto.PubKey, path hd.BIP44Params, algo SigningAlgo) Info { +func newLedgerInfo(name string, pub crypto.PubKey, path hd.BIP44Params, algo pubKeyType) Info { return &ledgerInfo{ Name: name, PubKey: pub, @@ -120,7 +120,7 @@ func (i ledgerInfo) GetAddress() types.AccAddress { } // GetPath implements Info interface -func (i ledgerInfo) GetAlgo() SigningAlgo { +func (i ledgerInfo) GetAlgo() pubKeyType { return i.Algo } @@ -135,10 +135,10 @@ func (i ledgerInfo) GetPath() (*hd.BIP44Params, error) { type offlineInfo struct { Name string `json:"name"` PubKey crypto.PubKey `json:"pubkey"` - Algo SigningAlgo `json:"algo"` + Algo pubKeyType `json:"algo"` } -func newOfflineInfo(name string, pub crypto.PubKey, algo SigningAlgo) Info { +func newOfflineInfo(name string, pub crypto.PubKey, algo pubKeyType) Info { return &offlineInfo{ Name: name, PubKey: pub, @@ -162,7 +162,7 @@ func (i offlineInfo) GetPubKey() crypto.PubKey { } // GetAlgo returns the signing algorithm for the key -func (i offlineInfo) GetAlgo() SigningAlgo { +func (i offlineInfo) GetAlgo() pubKeyType { return i.Algo } @@ -228,7 +228,7 @@ func (i multiInfo) GetAddress() types.AccAddress { } // GetPath implements Info interface -func (i multiInfo) GetAlgo() SigningAlgo { +func (i multiInfo) GetAlgo() pubKeyType { return MultiAlgo } diff --git a/crypto/keyring/keybase.go b/crypto/keyring/keybase.go index 149069ff50b..a88308abae9 100644 --- a/crypto/keyring/keybase.go +++ b/crypto/keyring/keybase.go @@ -25,17 +25,17 @@ type Keybase interface { // It returns the generated mnemonic and the key Info. It returns an error if it fails to // generate a key for the given algo type, or if another key is already stored under the // same name. - CreateMnemonic(name string, language Language, passwd string, algo SigningAlgo) (info Info, seed string, err error) + CreateMnemonic(name string, language Language, passwd string, algo pubKeyType) (info Info, seed string, err error) // CreateAccount converts a mnemonic to a private key and BIP 32 HD Path // and persists it, encrypted with the given password. - CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd, hdPath string, algo SigningAlgo) (Info, error) + CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd, hdPath string, algo pubKeyType) (Info, error) // CreateLedger creates, stores, and returns a new Ledger key reference - CreateLedger(name string, algo SigningAlgo, hrp string, account, index uint32) (info Info, err error) + CreateLedger(name string, algo pubKeyType, hrp string, account, index uint32) (info Info, err error) // CreateOffline creates, stores, and returns a new offline key reference - CreateOffline(name string, pubkey crypto.PubKey, algo SigningAlgo) (info Info, err error) + CreateOffline(name string, pubkey crypto.PubKey, algo pubKeyType) (info Info, err error) // CreateMulti creates, stores, and returns a new multsig (offline) key reference CreateMulti(name string, pubkey crypto.PubKey) (info Info, err error) @@ -69,8 +69,8 @@ type Keybase interface { ExportPrivateKeyObject(name string, passphrase string) (crypto.PrivKey, error) // SupportedAlgos returns a list of signing algorithms supported by the keybase - SupportedAlgos() []SigningAlgo + SupportedAlgos() []pubKeyType // SupportedAlgosLedger returns a list of signing algorithms supported by the keybase's ledger integration - SupportedAlgosLedger() []SigningAlgo + SupportedAlgosLedger() []pubKeyType } diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 07c5310a0a2..855c5a35d14 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -102,7 +102,7 @@ func NewInMemory(opts ...KeybaseOption) Keybase { // An error is returned if it fails to generate a key for the given algo type, // or if another key is already stored under the same name. func (kb keyringKeybase) CreateMnemonic( - name string, language Language, passwd string, algo SigningAlgo, + name string, language Language, passwd string, algo pubKeyType, ) (info Info, mnemonic string, err error) { return kb.base.CreateMnemonic(kb, name, language, passwd, algo) @@ -111,7 +111,7 @@ func (kb keyringKeybase) CreateMnemonic( // CreateAccount converts a mnemonic to a private key and persists it, encrypted // with the given password. func (kb keyringKeybase) CreateAccount( - name, mnemonic, bip39Passwd, encryptPasswd, hdPath string, algo SigningAlgo, + name, mnemonic, bip39Passwd, encryptPasswd, hdPath string, algo pubKeyType, ) (Info, error) { return kb.base.CreateAccount(kb, name, mnemonic, bip39Passwd, encryptPasswd, hdPath, algo) @@ -120,7 +120,7 @@ func (kb keyringKeybase) CreateAccount( // CreateLedger creates a new locally-stored reference to a Ledger keypair. // It returns the created key info and an error if the Ledger could not be queried. func (kb keyringKeybase) CreateLedger( - name string, algo SigningAlgo, hrp string, account, index uint32, + name string, algo pubKeyType, hrp string, account, index uint32, ) (Info, error) { return kb.base.CreateLedger(kb, name, algo, hrp, account, index) @@ -128,7 +128,7 @@ func (kb keyringKeybase) CreateLedger( // CreateOffline creates a new reference to an offline keypair. It returns the // created key info. -func (kb keyringKeybase) CreateOffline(name string, pub tmcrypto.PubKey, algo SigningAlgo) (Info, error) { +func (kb keyringKeybase) CreateOffline(name string, pub tmcrypto.PubKey, algo pubKeyType) (Info, error) { return kb.base.writeOfflineKey(kb, name, pub, algo), nil } @@ -364,7 +364,7 @@ func (kb keyringKeybase) ImportPrivKey(name, armor, passphrase string) error { } // NOTE: The keyring keystore has no need for a passphrase. - kb.writeLocalKey(name, privKey, SigningAlgo(algo)) + kb.writeLocalKey(name, privKey, pubKeyType(algo)) return nil } @@ -397,7 +397,7 @@ func (kb keyringKeybase) ImportPubKey(name string, armor string) error { return err } - kb.base.writeOfflineKey(kb, name, pubKey, SigningAlgo(algo)) + kb.base.writeOfflineKey(kb, name, pubKey, pubKeyType(algo)) return nil } @@ -426,16 +426,16 @@ func (kb keyringKeybase) Delete(name, _ string, _ bool) error { } // SupportedAlgos returns a list of supported signing algorithms. -func (kb keyringKeybase) SupportedAlgos() []SigningAlgo { +func (kb keyringKeybase) SupportedAlgos() []pubKeyType { return kb.base.SupportedAlgos() } // SupportedAlgosLedger returns a list of supported ledger signing algorithms. -func (kb keyringKeybase) SupportedAlgosLedger() []SigningAlgo { +func (kb keyringKeybase) SupportedAlgosLedger() []pubKeyType { return kb.base.SupportedAlgosLedger() } -func (kb keyringKeybase) writeLocalKey(name string, priv tmcrypto.PrivKey, algo SigningAlgo) Info { +func (kb keyringKeybase) writeLocalKey(name string, priv tmcrypto.PrivKey, algo pubKeyType) Info { // encrypt private key using keyring pub := priv.PubKey() info := newLocalInfo(name, pub, string(priv.Bytes()), algo) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 83cd5a409d3..d57875edcb4 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -429,12 +429,12 @@ func TestSupportedAlgos(t *testing.T) { t.Cleanup(cleanup) kb, err := NewKeyring("keybasename", "test", dir, nil) require.NoError(t, err) - require.Equal(t, []SigningAlgo{"secp256k1"}, kb.SupportedAlgos()) - require.Equal(t, []SigningAlgo{"secp256k1"}, kb.SupportedAlgosLedger()) + require.Equal(t, []pubKeyType{"secp256k1"}, kb.SupportedAlgos()) + require.Equal(t, []pubKeyType{"secp256k1"}, kb.SupportedAlgosLedger()) } func TestCustomDerivFuncKey(t *testing.T) { - kb := NewInMemory(WithDeriveFunc(func(mnemonic string, bip39Passphrase, hdPath string, algo SigningAlgo) ([]byte, error) { + kb := NewInMemory(WithDeriveFunc(func(mnemonic string, bip39Passphrase, hdPath string, algo pubKeyType) ([]byte, error) { return nil, errors.New("cannot derive keys") })) _, _, err := kb.CreateMnemonic("test", English, "", "") @@ -485,7 +485,7 @@ func TestInMemoryCreateLedgerUnsupportedAlgo(t *testing.T) { } func TestInMemoryCreateLedger(t *testing.T) { - kb := NewInMemory(WithSupportedAlgosLedger([]SigningAlgo{Secp256k1, Ed25519})) + kb := NewInMemory(WithSupportedAlgosLedger([]pubKeyType{Secp256k1, Ed25519})) // test_cover and test_unit will result in different answers // test_cover does not compile some dependencies so ledger is disabled @@ -536,7 +536,7 @@ func TestInMemoryCreateLedger(t *testing.T) { // TestInMemoryKeyManagement makes sure we can manipulate these keys well func TestInMemoryKeyManagement(t *testing.T) { // make the storage with reasonable defaults - cstore := NewInMemory(WithSupportedAlgos([]SigningAlgo{Secp256k1, Sr25519})) + cstore := NewInMemory(WithSupportedAlgos([]pubKeyType{Secp256k1, Sr25519})) // Test modified supported algos supportedAlgos := cstore.SupportedAlgos() @@ -885,7 +885,7 @@ func TestInMemorySeedPhrase(t *testing.T) { func ExampleNew() { // Select the encryption and storage for your cryptostore - customKeyGenFunc := func(bz []byte, algo SigningAlgo) (tmcrypto.PrivKey, error) { + customKeyGenFunc := func(bz []byte, algo pubKeyType) (tmcrypto.PrivKey, error) { var bzArr [32]byte copy(bzArr[:], bz) return secp256k1.PrivKeySecp256k1(bzArr), nil @@ -985,7 +985,7 @@ func TestInMemoryKeygenOverride(t *testing.T) { CryptoCdc = testCdc overrideCalled := false - dummyFunc := func(bz []byte, algo SigningAlgo) (tmcrypto.PrivKey, error) { + dummyFunc := func(bz []byte, algo pubKeyType) (tmcrypto.PrivKey, error) { overrideCalled = true return testPriv(bz), nil } diff --git a/crypto/keyring/options.go b/crypto/keyring/options.go index 21e69398f00..b7ad9903102 100644 --- a/crypto/keyring/options.go +++ b/crypto/keyring/options.go @@ -6,8 +6,8 @@ type KeybaseOption func(*kbOptions) type kbOptions struct { keygenFunc PrivKeyGenFunc deriveFunc DeriveKeyFunc - supportedAlgos []SigningAlgo - supportedAlgosLedger []SigningAlgo + supportedAlgos []pubKeyType + supportedAlgosLedger []pubKeyType } // WithKeygenFunc applies an overridden key generation function to generate the private key. @@ -25,14 +25,14 @@ func WithDeriveFunc(f DeriveKeyFunc) KeybaseOption { } // WithSupportedAlgos defines the list of accepted SigningAlgos. -func WithSupportedAlgos(algos []SigningAlgo) KeybaseOption { +func WithSupportedAlgos(algos []pubKeyType) KeybaseOption { return func(o *kbOptions) { o.supportedAlgos = algos } } // WithSupportedAlgosLedger defines the list of accepted SigningAlgos compatible with Ledger. -func WithSupportedAlgosLedger(algos []SigningAlgo) KeybaseOption { +func WithSupportedAlgosLedger(algos []pubKeyType) KeybaseOption { return func(o *kbOptions) { o.supportedAlgosLedger = algos } diff --git a/crypto/keyring/signing_algorithms.go b/crypto/keyring/signing_algorithms.go index 12e000aeb9d..5ddfb28d660 100644 --- a/crypto/keyring/signing_algorithms.go +++ b/crypto/keyring/signing_algorithms.go @@ -1,22 +1,22 @@ package keyring -// SigningAlgo defines an algorithm to derive key-pairs which can be used for cryptographic signing. -type SigningAlgo string +// pubKeyType defines an algorithm to derive key-pairs which can be used for cryptographic signing. +type pubKeyType string const ( // MultiAlgo implies that a pubkey is a multisignature - MultiAlgo = SigningAlgo("multi") + MultiAlgo = pubKeyType("multi") // Secp256k1 uses the Bitcoin secp256k1 ECDSA parameters. - Secp256k1 = SigningAlgo("secp256k1") + Secp256k1 = pubKeyType("secp256k1") // Ed25519 represents the Ed25519 signature system. // It is currently not supported for end-user keys (wallets/ledgers). - Ed25519 = SigningAlgo("ed25519") + Ed25519 = pubKeyType("ed25519") // Sr25519 represents the Sr25519 signature system. - Sr25519 = SigningAlgo("sr25519") + Sr25519 = pubKeyType("sr25519") ) // IsSupportedAlgorithm returns whether the signing algorithm is in the passed-in list of supported algorithms. -func IsSupportedAlgorithm(supported []SigningAlgo, algo SigningAlgo) bool { +func IsSupportedAlgorithm(supported []pubKeyType, algo pubKeyType) bool { for _, supportedAlgo := range supported { if algo == supportedAlgo { return true diff --git a/crypto/keyring/types.go b/crypto/keyring/types.go index fadf47ad588..0e48d9cdbab 100644 --- a/crypto/keyring/types.go +++ b/crypto/keyring/types.go @@ -62,7 +62,7 @@ func (kt KeyType) String() string { type ( // DeriveKeyFunc defines the function to derive a new key from a seed and hd path - DeriveKeyFunc func(mnemonic string, bip39Passphrase, hdPath string, algo SigningAlgo) ([]byte, error) + DeriveKeyFunc func(mnemonic string, bip39Passphrase, hdPath string, algo pubKeyType) ([]byte, error) // PrivKeyGenFunc defines the function to convert derived key bytes to a tendermint private key - PrivKeyGenFunc func(bz []byte, algo SigningAlgo) (crypto.PrivKey, error) + PrivKeyGenFunc func(bz []byte, algo pubKeyType) (crypto.PrivKey, error) ) From 02b70cb8609ff4ef83b1638cb04b20298f6b3ba6 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Wed, 1 Apr 2020 19:05:08 +0200 Subject: [PATCH 070/148] Move the new interface into keyring.go Add a panic when BackendMemory is used for now. --- crypto/keyring/altkeyring.go | 67 ++---------------------------------- crypto/keyring/keyring.go | 65 ++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 65 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index ef3cff06252..042413b47d7 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -22,71 +22,6 @@ var ( _ Keyring = &altKeyring{} ) -// Keyring exposes operations on a generic keystore -type Keyring interface { - // List all keys. - List() ([]Info, error) - - // Key and KeyByAddress return keys by uid and address respectively. - Key(uid string) (Info, error) - KeyByAddress(address types.Address) (Info, error) - - //// Delete and DeleteByAddress remove keys. - Delete(uid string) error - DeleteByAddress(address types.Address) error - - // NewMnemonic generates a new mnemonic, derives a hierarchical deterministic - // key from that, and persists it to storage. Returns the generated mnemonic and the key - // Info. It returns an error if it fails to generate a key for the given algo type, or if - // another key is already stored under the same name. - NewMnemonic(uid string, language Language, algo AltSigningAlgo) (Info, string, error) - - // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. - NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo AltSigningAlgo) (Info, error) - - // SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. - SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, account, index uint32) (Info, error) - - // SavePubKey stores a public key and returns the persisted Info structure. - SavePubKey(uid string, pubkey tmcrypto.PubKey, algo AltSigningAlgo) (Info, error) - - // SaveMultisig stores, stores, and returns a new multsig (offline) key reference - SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) - - Signer - - Importer - Exporter -} - -// Signer is implemented by key stores that want to provide signing capabilities. -type Signer interface { - // Sign sign byte messages with a user key. - Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error) - - // SignByAddress sign byte messages with a user key providing the address. - SignByAddress(address types.Address, msg []byte) ([]byte, tmcrypto.PubKey, error) -} - -// Importer is implemented by key stores that support import of public and private keys. -type Importer interface { - ImportPrivKey(uid, armor, passphrase string) error - ImportPubKey(uid string, armor string) error -} - -// Exporter is implemented by key stores that support export of public and private keys. -type Exporter interface { - // Export public key - ExportPubKeyArmor(uid string) (string, error) - ExportPubKeyArmorByAddress(address types.Address) (string, error) - // 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. - ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) - ExportPrivKeyArmorByAddress(address types.Address, encryptPassphrase string) (armor string, err error) -} - -type AltKeyringOption func(options *altKrOptions) - // NewKeyring creates a new instance of a keyring. Keybase // options can be applied when generating this new Keybase. // Available backends are "os", "file", "kwallet", "pass", "test". @@ -98,6 +33,8 @@ func NewAltKeyring( var err error switch backend { + case BackendMemory: + panic("not implemented") case BackendTest: db, err = keyring.Open(lkbToKeyringConfig(appName, rootDir, nil, true)) case BackendFile: diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 855c5a35d14..024b2562360 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -41,6 +41,71 @@ const ( var _ Keybase = keyringKeybase{} +// Keyring exposes operations over a backend supported by github.com/99designs/keyring. +type Keyring interface { + // List all keys. + List() ([]Info, error) + + // Key and KeyByAddress return keys by uid and address respectively. + Key(uid string) (Info, error) + KeyByAddress(address types.Address) (Info, error) + + // Delete and DeleteByAddress remove keys from the keyring. + Delete(uid string) error + DeleteByAddress(address types.Address) error + + // NewMnemonic generates a new mnemonic, derives a hierarchical deterministic + // key from that, and persists it to the storage. Returns the generated mnemonic and the key + // Info. It returns an error if it fails to generate a key for the given algo type, or if + // another key is already stored under the same name. + NewMnemonic(uid string, language Language, algo AltSigningAlgo) (Info, string, error) + + // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. + NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo AltSigningAlgo) (Info, error) + + // SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. + SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, account, index uint32) (Info, error) + + // SavePubKey stores a public key and returns the persisted Info structure. + SavePubKey(uid string, pubkey tmcrypto.PubKey, algo AltSigningAlgo) (Info, error) + + // SaveMultisig stores and returns a new multsig (offline) key reference. + SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) + + Signer + + Importer + Exporter +} + +// Signer is implemented by key stores that want to provide signing capabilities. +type Signer interface { + // Sign sign byte messages with a user key. + Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error) + + // SignByAddress sign byte messages with a user key providing the address. + SignByAddress(address types.Address, msg []byte) ([]byte, tmcrypto.PubKey, error) +} + +// Importer is implemented by key stores that support import of public and private keys. +type Importer interface { + ImportPrivKey(uid, armor, passphrase string) error + ImportPubKey(uid string, armor string) error +} + +// Exporter is implemented by key stores that support export of public and private keys. +type Exporter interface { + // Export public key + ExportPubKeyArmor(uid string) (string, error) + ExportPubKeyArmorByAddress(address types.Address) (string, error) + // 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. + ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) + ExportPrivKeyArmorByAddress(address types.Address, encryptPassphrase string) (armor string, err error) +} + +type AltKeyringOption func(options *altKrOptions) + // keyringKeybase implements the Keybase interface by using the Keyring library // for account key persistence. type keyringKeybase struct { From 4474f7711423e0c299e12ad3aea996b6ab257bd1 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Wed, 1 Apr 2020 20:44:44 +0200 Subject: [PATCH 071/148] Rename NewAltKeyring() -> New() --- crypto/keyring/altkeyring.go | 2 +- crypto/keyring/altkeyring_test.go | 34 +++++++++++++++---------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 042413b47d7..c45ff29cb0f 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -25,7 +25,7 @@ var ( // NewKeyring creates a new instance of a keyring. Keybase // options can be applied when generating this new Keybase. // Available backends are "os", "file", "kwallet", "pass", "test". -func NewAltKeyring( +func New( appName, backend, rootDir string, userInput io.Reader, opts ...AltKeyringOption, ) (Keyring, error) { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 8178fa0f7bd..9dfe0e5bd07 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -26,7 +26,7 @@ func TestAltKeyring_List(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) - keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) list, err := keyring.List() @@ -60,7 +60,7 @@ func TestAltKeyring_NewAccount(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) - keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) entropy, err := bip39.NewEntropy(defaultEntropySize) @@ -89,7 +89,7 @@ func TestAltKeyring_SaveLedgerKey(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) - keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) // Test unsupported Algo @@ -109,7 +109,7 @@ func TestAltKeyring_Get(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) - keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) uid := someKey @@ -125,7 +125,7 @@ func TestAltKeyring_KeyByAddress(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) - keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) uid := someKey @@ -141,7 +141,7 @@ func TestAltKeyring_Delete(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) - keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) uid := someKey @@ -164,7 +164,7 @@ func TestAltKeyring_DeleteByAddress(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) - keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) uid := someKey @@ -187,7 +187,7 @@ func TestAltKeyring_SavePubKey(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) - keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) list, err := keyring.List() @@ -213,7 +213,7 @@ func TestAltKeyring_SaveMultisig(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) - keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) mnemonic1, _, err := keyring.NewMnemonic("key1", English, AltSecp256k1) @@ -238,7 +238,7 @@ func TestAltKeyring_Sign(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) - keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) uid := "jack" @@ -257,7 +257,7 @@ func TestAltKeyring_SignByAddress(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) - keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) uid := "jack" @@ -276,7 +276,7 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) - keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) uid := theID @@ -304,7 +304,7 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) - keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) uid := theID @@ -332,7 +332,7 @@ func TestAltKeyring_ImportExportPubKey(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) - keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) uid := theID @@ -355,7 +355,7 @@ func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) - keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) uid := theID @@ -378,7 +378,7 @@ func TestAltKeyring_ConstructorSupportedAlgos(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) - keyring, err := NewAltKeyring(t.Name(), BackendTest, dir, nil) + keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) // should fail when using unsupported signing algorythm. @@ -393,7 +393,7 @@ func TestAltKeyring_ConstructorSupportedAlgos(t *testing.T) { dir2, clean2 := tests.NewTestCaseDir(t) t.Cleanup(clean2) - keyring2, err := NewAltKeyring(t.Name(), BackendTest, dir2, nil, func(options *altKrOptions) { + keyring2, err := New(t.Name(), BackendTest, dir2, nil, func(options *altKrOptions) { options.supportedAlgos = AltSigningAlgoList{ notSupportedAlgo{}, } From 303a334175be6c3449de356749688e72502a6eca Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Wed, 1 Apr 2020 20:49:16 +0200 Subject: [PATCH 072/148] More renaming --- crypto/keyring/altkeyring.go | 140 +++++++++++++++++------------------ 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index c45ff29cb0f..49e0973930f 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -19,7 +19,7 @@ import ( ) var ( - _ Keyring = &altKeyring{} + _ Keyring = &keystore{} ) // NewKeyring creates a new instance of a keyring. Keybase @@ -63,19 +63,19 @@ func New( optionFn(&options) } - return altKeyring{ + return keystore{ db: db, options: options, }, nil } -type altKeyring struct { +type keystore struct { db keyring.Keyring options altKrOptions } -func (a altKeyring) ExportPubKeyArmor(uid string) (string, error) { - bz, err := a.Key(uid) +func (ks keystore) ExportPubKeyArmor(uid string) (string, error) { + bz, err := ks.Key(uid) if err != nil { return "", err } @@ -87,22 +87,22 @@ func (a altKeyring) ExportPubKeyArmor(uid string) (string, error) { return crypto.ArmorPubKeyBytes(bz.GetPubKey().Bytes(), string(bz.GetAlgo())), nil } -func (a altKeyring) ExportPubKeyArmorByAddress(address types.Address) (string, error) { - info, err := a.KeyByAddress(address) +func (ks keystore) ExportPubKeyArmorByAddress(address types.Address) (string, error) { + info, err := ks.KeyByAddress(address) if err != nil { return "", err } - return a.ExportPubKeyArmor(info.GetName()) + return ks.ExportPubKeyArmor(info.GetName()) } -func (a altKeyring) ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) { - priv, err := a.ExportPrivateKeyObject(uid) +func (ks keystore) ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) { + priv, err := ks.ExportPrivateKeyObject(uid) if err != nil { return "", err } - info, err := a.Key(uid) + info, err := ks.Key(uid) if err != nil { return "", err } @@ -111,8 +111,8 @@ func (a altKeyring) ExportPrivKeyArmor(uid, encryptPassphrase string) (armor str } // ExportPrivateKeyObject exports an armored private key object. -func (a altKeyring) ExportPrivateKeyObject(uid string) (tmcrypto.PrivKey, error) { - info, err := a.Key(uid) +func (ks keystore) ExportPrivateKeyObject(uid string) (tmcrypto.PrivKey, error) { + info, err := ks.Key(uid) if err != nil { return nil, err } @@ -138,17 +138,17 @@ func (a altKeyring) ExportPrivateKeyObject(uid string) (tmcrypto.PrivKey, error) return priv, nil } -func (a altKeyring) ExportPrivKeyArmorByAddress(address types.Address, encryptPassphrase string) (armor string, err error) { - byAddress, err := a.KeyByAddress(address) +func (ks keystore) ExportPrivKeyArmorByAddress(address types.Address, encryptPassphrase string) (armor string, err error) { + byAddress, err := ks.KeyByAddress(address) if err != nil { return "", err } - return a.ExportPrivKeyArmor(byAddress.GetName(), encryptPassphrase) + return ks.ExportPrivKeyArmor(byAddress.GetName(), encryptPassphrase) } -func (a altKeyring) ImportPrivKey(uid, armor, passphrase string) error { - if a.hasKey(uid) { +func (ks keystore) ImportPrivKey(uid, armor, passphrase string) error { + if ks.hasKey(uid) { return fmt.Errorf("cannot overwrite key: %s", uid) } @@ -157,7 +157,7 @@ func (a altKeyring) ImportPrivKey(uid, armor, passphrase string) error { return errors.Wrap(err, "failed to decrypt private key") } - _, err = a.writeLocalKey(uid, privKey, pubKeyType(algo)) + _, err = ks.writeLocalKey(uid, privKey, pubKeyType(algo)) if err != nil { return err } @@ -166,13 +166,13 @@ func (a altKeyring) ImportPrivKey(uid, armor, passphrase string) error { } // HasKey returns whether the key exists in the keyring. -func (a altKeyring) hasKey(name string) bool { - bz, _ := a.Key(name) +func (ks keystore) hasKey(name string) bool { + bz, _ := ks.Key(name) return bz != nil } -func (a altKeyring) ImportPubKey(uid string, armor string) error { - bz, _ := a.Key(uid) +func (ks keystore) ImportPubKey(uid string, armor string) error { + bz, _ := ks.Key(uid) if bz != nil { pubkey := bz.GetPubKey() @@ -191,7 +191,7 @@ func (a altKeyring) ImportPubKey(uid string, armor string) error { return err } - _, err = a.writeOfflineKey(uid, pubKey, pubKeyType(algo)) + _, err = ks.writeOfflineKey(uid, pubKey, pubKeyType(algo)) if err != nil { return err } @@ -199,8 +199,8 @@ func (a altKeyring) ImportPubKey(uid string, armor string) error { return nil } -func (a altKeyring) Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error) { - info, err := a.Key(uid) +func (ks keystore) Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error) { + info, err := ks.Key(uid) if err != nil { return nil, nil, err } @@ -233,17 +233,17 @@ func (a altKeyring) Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error return sig, priv.PubKey(), nil } -func (a altKeyring) SignByAddress(address types.Address, msg []byte) ([]byte, tmcrypto.PubKey, error) { - key, err := a.KeyByAddress(address) +func (ks keystore) SignByAddress(address types.Address, msg []byte) ([]byte, tmcrypto.PubKey, error) { + key, err := ks.KeyByAddress(address) if err != nil { return nil, nil, err } - return a.Sign(key.GetName(), msg) + return ks.Sign(key.GetName(), msg) } -func (a altKeyring) SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, account, index uint32) (Info, error) { - if !a.options.supportedAlgosLedger.Contains(algo) { +func (ks keystore) SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, account, index uint32) (Info, error) { + if !ks.options.supportedAlgosLedger.Contains(algo) { return nil, ErrUnsupportedSigningAlgo } @@ -255,12 +255,12 @@ func (a altKeyring) SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, a return nil, err } - return a.writeLedgerKey(uid, priv.PubKey(), *hdPath, algo.Name()) + return ks.writeLedgerKey(uid, priv.PubKey(), *hdPath, algo.Name()) } -func (a altKeyring) writeLedgerKey(name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo pubKeyType) (Info, error) { +func (ks keystore) writeLedgerKey(name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo pubKeyType) (Info, error) { info := newLedgerInfo(name, pub, path, algo) - err := a.writeInfo(name, info) + err := ks.writeInfo(name, info) if err != nil { return nil, err } @@ -273,21 +273,21 @@ type altKrOptions struct { supportedAlgosLedger AltSigningAlgoList } -func (a altKeyring) SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) { - return a.writeMultisigKey(uid, pubkey) +func (ks keystore) SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) { + return ks.writeMultisigKey(uid, pubkey) } -func (a altKeyring) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo AltSigningAlgo) (Info, error) { - return a.writeOfflineKey(uid, pubkey, algo.Name()) +func (ks keystore) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo AltSigningAlgo) (Info, error) { + return ks.writeOfflineKey(uid, pubkey, algo.Name()) } -func (a altKeyring) DeleteByAddress(address types.Address) error { - info, err := a.KeyByAddress(address) +func (ks keystore) DeleteByAddress(address types.Address) error { + info, err := ks.KeyByAddress(address) if err != nil { return err } - err = a.Delete(info.GetName()) + err = ks.Delete(info.GetName()) if err != nil { return err } @@ -295,18 +295,18 @@ func (a altKeyring) DeleteByAddress(address types.Address) error { return nil } -func (a altKeyring) Delete(uid string) error { - info, err := a.Key(uid) +func (ks keystore) Delete(uid string) error { + info, err := ks.Key(uid) if err != nil { return err } - err = a.db.Remove(addrHexKeyAsString(info.GetAddress())) + err = ks.db.Remove(addrHexKeyAsString(info.GetAddress())) if err != nil { return err } - err = a.db.Remove(string(infoKey(uid))) + err = ks.db.Remove(string(infoKey(uid))) if err != nil { return err } @@ -314,8 +314,8 @@ func (a altKeyring) Delete(uid string) error { return nil } -func (a altKeyring) KeyByAddress(address types.Address) (Info, error) { - ik, err := a.db.Get(addrHexKeyAsString(address)) +func (ks keystore) KeyByAddress(address types.Address) (Info, error) { + ik, err := ks.db.Get(addrHexKeyAsString(address)) if err != nil { return nil, err } @@ -324,7 +324,7 @@ func (a altKeyring) KeyByAddress(address types.Address) (Info, error) { return nil, fmt.Errorf("key with address %s not found", address) } - bs, err := a.db.Get(string(ik.Data)) + bs, err := ks.db.Get(string(ik.Data)) if err != nil { return nil, err } @@ -332,9 +332,9 @@ func (a altKeyring) KeyByAddress(address types.Address) (Info, error) { return unmarshalInfo(bs.Data) } -func (a altKeyring) List() ([]Info, error) { +func (ks keystore) List() ([]Info, error) { var res []Info - keys, err := a.db.Keys() + keys, err := ks.db.Keys() if err != nil { return nil, err } @@ -343,7 +343,7 @@ func (a altKeyring) List() ([]Info, error) { for _, key := range keys { if strings.HasSuffix(key, infoSuffix) { - rawInfo, err := a.db.Get(key) + rawInfo, err := ks.db.Get(key) if err != nil { return nil, err } @@ -364,12 +364,12 @@ func (a altKeyring) List() ([]Info, error) { return res, nil } -func (a altKeyring) NewMnemonic(uid string, language Language, algo AltSigningAlgo) (Info, string, error) { +func (ks keystore) NewMnemonic(uid string, language Language, algo AltSigningAlgo) (Info, string, error) { if language != English { return nil, "", ErrUnsupportedLanguage } - if !a.isSupportedSigningAlgo(algo) { + if !ks.isSupportedSigningAlgo(algo) { return nil, "", ErrUnsupportedSigningAlgo } @@ -385,7 +385,7 @@ func (a altKeyring) NewMnemonic(uid string, language Language, algo AltSigningAl return nil, "", err } - info, err := a.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), algo) + info, err := ks.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), algo) if err != nil { return nil, "", err } @@ -393,8 +393,8 @@ func (a altKeyring) NewMnemonic(uid string, language Language, algo AltSigningAl return info, mnemonic, err } -func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase string, hdPath string, algo AltSigningAlgo) (Info, error) { - if !a.isSupportedSigningAlgo(algo) { +func (ks keystore) NewAccount(uid string, mnemonic string, bip39Passphrase string, hdPath string, algo AltSigningAlgo) (Info, error) { + if !ks.isSupportedSigningAlgo(algo) { return nil, ErrUnsupportedSigningAlgo } @@ -406,17 +406,17 @@ func (a altKeyring) NewAccount(uid string, mnemonic string, bip39Passphrase stri privKey := algo.PrivKeyGen()(derivedPriv) - return a.writeLocalKey(uid, privKey, algo.Name()) + return ks.writeLocalKey(uid, privKey, algo.Name()) } -func (a altKeyring) isSupportedSigningAlgo(algo AltSigningAlgo) bool { - return a.options.supportedAlgos.Contains(algo) +func (ks keystore) isSupportedSigningAlgo(algo AltSigningAlgo) bool { + return ks.options.supportedAlgos.Contains(algo) } -func (a altKeyring) Key(uid string) (Info, error) { +func (ks keystore) Key(uid string) (Info, error) { key := infoKey(uid) - bs, err := a.db.Get(string(key)) + bs, err := ks.db.Get(string(key)) if err != nil { return nil, err } @@ -428,12 +428,12 @@ func (a altKeyring) Key(uid string) (Info, error) { return unmarshalInfo(bs.Data) } -func (a altKeyring) writeLocalKey(name string, priv tmcrypto.PrivKey, algo pubKeyType) (Info, error) { +func (ks keystore) writeLocalKey(name string, priv tmcrypto.PrivKey, algo pubKeyType) (Info, error) { // encrypt private key using keyring pub := priv.PubKey() info := newLocalInfo(name, pub, string(priv.Bytes()), algo) - err := a.writeInfo(name, info) + err := ks.writeInfo(name, info) if err != nil { return nil, err } @@ -441,12 +441,12 @@ func (a altKeyring) writeLocalKey(name string, priv tmcrypto.PrivKey, algo pubKe return info, nil } -func (a altKeyring) writeInfo(name string, info Info) error { +func (ks keystore) writeInfo(name string, info Info) error { // write the info by key key := infoKey(name) serializedInfo := marshalInfo(info) - err := a.db.Set(keyring.Item{ + err := ks.db.Set(keyring.Item{ Key: string(key), Data: serializedInfo, }) @@ -454,7 +454,7 @@ func (a altKeyring) writeInfo(name string, info Info) error { return err } - err = a.db.Set(keyring.Item{ + err = ks.db.Set(keyring.Item{ Key: addrHexKeyAsString(info.GetAddress()), Data: key, }) @@ -465,9 +465,9 @@ func (a altKeyring) writeInfo(name string, info Info) error { return nil } -func (a altKeyring) writeOfflineKey(name string, pub tmcrypto.PubKey, algo pubKeyType) (Info, error) { +func (ks keystore) writeOfflineKey(name string, pub tmcrypto.PubKey, algo pubKeyType) (Info, error) { info := newOfflineInfo(name, pub, algo) - err := a.writeInfo(name, info) + err := ks.writeInfo(name, info) if err != nil { return nil, err } @@ -475,9 +475,9 @@ func (a altKeyring) writeOfflineKey(name string, pub tmcrypto.PubKey, algo pubKe return info, nil } -func (a altKeyring) writeMultisigKey(name string, pub tmcrypto.PubKey) (Info, error) { +func (ks keystore) writeMultisigKey(name string, pub tmcrypto.PubKey) (Info, error) { info := NewMultiInfo(name, pub) - err := a.writeInfo(name, info) + err := ks.writeInfo(name, info) if err != nil { return nil, err } From 2f525d27a918971b4f36c9c1796c49d02c55d3db Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 11:34:53 +0200 Subject: [PATCH 073/148] add constructor --- client/keys/add.go | 33 +++++++--------- crypto/keyring/alt_signing_algorithms.go | 14 ++++++- crypto/keyring/alt_signing_algorithms_test.go | 39 +++++++++++++++++++ 3 files changed, 65 insertions(+), 21 deletions(-) diff --git a/client/keys/add.go b/client/keys/add.go index 1170c714ee3..cf6f370c9cf 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -80,12 +80,12 @@ the flag --nosort is set. return cmd } -func getKeybase(transient bool, buf io.Reader) (keyring.Keybase, error) { +func getKeybase(transient bool, buf io.Reader) (keyring.Keyring, error) { if transient { - return keyring.NewKeyring(sdk.KeyringServiceName(), keyring.BackendMemory, viper.GetString(flags.FlagHome), buf) + return keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, viper.GetString(flags.FlagHome), buf) } - return keyring.NewKeyring(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), buf) + return keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), buf) } func runAddCmd(cmd *cobra.Command, args []string) error { @@ -107,7 +107,7 @@ input output - armor encrypted private key (saved to file) */ -func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keybase, inBuf *bufio.Reader) error { +func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *bufio.Reader) error { var err error name := args[0] @@ -115,16 +115,13 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keybase, inBuf *buf interactive := viper.GetBool(flagInteractive) showMnemonic := !viper.GetBool(flagNoBackup) - algo := keyring.SigningAlgo(viper.GetString(flagKeyAlgo)) - if algo == keyring.SigningAlgo("") { - algo = keyring.Secp256k1 - } - if !keyring.IsSupportedAlgorithm(kb.SupportedAlgos(), algo) { - return keyring.ErrUnsupportedSigningAlgo + algo, err := keyring.NewSigningAlgoFromString(viper.GetString(flagKeyAlgo)) + if err != nil { + algo = keyring.AltSecp256k1 } if !viper.GetBool(flags.FlagDryRun) { - _, err = kb.Get(name) + _, err = kb.Key(name) if err == nil { // account exists, ask for user confirmation response, err2 := input.GetConfirmation(fmt.Sprintf("override the existing name %s", name), inBuf) @@ -146,7 +143,7 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keybase, inBuf *buf } for _, keyname := range multisigKeys { - k, err := kb.Get(keyname) + k, err := kb.Key(keyname) if err != nil { return err } @@ -161,7 +158,7 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keybase, inBuf *buf } pk := multisig.NewPubKeyMultisigThreshold(multisigThreshold, pks) - if _, err := kb.CreateMulti(name, pk); err != nil { + if _, err := kb.SaveMultisig(name, pk); err != nil { return err } @@ -175,7 +172,7 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keybase, inBuf *buf if err != nil { return err } - _, err = kb.CreateOffline(name, pk, algo) + _, err = kb.SavePubKey(name, pk, algo) if err != nil { return err } @@ -201,12 +198,8 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keybase, inBuf *buf return errors.New("cannot set custom bip32 path with ledger") } - if !keyring.IsSupportedAlgorithm(kb.SupportedAlgosLedger(), algo) { - return keyring.ErrUnsupportedSigningAlgo - } - bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix() - info, err := kb.CreateLedger(name, keyring.Secp256k1, bech32PrefixAccAddr, account, index) + info, err := kb.SaveLedgerKey(name, keyring.AltSecp256k1, bech32PrefixAccAddr, account, index) if err != nil { return err } @@ -269,7 +262,7 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keybase, inBuf *buf } } - info, err := kb.CreateAccount(name, mnemonic, bip39Passphrase, DefaultKeyPass, hdPath, algo) + info, err := kb.NewAccount(name, mnemonic, bip39Passphrase, hdPath, algo) if err != nil { return err } diff --git a/crypto/keyring/alt_signing_algorithms.go b/crypto/keyring/alt_signing_algorithms.go index 69b78cba811..8876c4a8f5c 100644 --- a/crypto/keyring/alt_signing_algorithms.go +++ b/crypto/keyring/alt_signing_algorithms.go @@ -1,6 +1,10 @@ package keyring -import "github.com/tendermint/tendermint/crypto" +import ( + "fmt" + + "github.com/tendermint/tendermint/crypto" +) type AltSigningAlgo interface { Name() pubKeyType @@ -11,6 +15,14 @@ type AltSigningAlgo interface { type AltDeriveKeyFunc func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) type AltPrivKeyGenFunc func(bz []byte) crypto.PrivKey +func NewSigningAlgoFromString(str string) (AltSigningAlgo, error) { + if str != string(AltSecp256k1.Name()) { + return nil, fmt.Errorf("provided algorithm `%s` is not supported", str) + } + + return AltSecp256k1, nil +} + type secp256k1Algo struct { } diff --git a/crypto/keyring/alt_signing_algorithms_test.go b/crypto/keyring/alt_signing_algorithms_test.go index f210538fe50..ad9b09b7f7f 100644 --- a/crypto/keyring/alt_signing_algorithms_test.go +++ b/crypto/keyring/alt_signing_algorithms_test.go @@ -1,11 +1,50 @@ package keyring import ( + "fmt" "testing" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/assert" ) +func TestNewSigningAlgoByString(t *testing.T) { + tests := []struct { + name string + algoStr string + isSupported bool + expectedAlgo AltSigningAlgo + expectedErr error + }{ + { + "supported algorithm", + "secp256k1", + true, + AltSecp256k1, + nil, + }, + { + "not supported", + "notsupportedalgo", + false, + nil, + fmt.Errorf("provided algorithm `notsupportedalgo` is not supported"), + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + algo, err := NewSigningAlgoFromString(tt.algoStr) + if tt.isSupported { + require.Equal(t, AltSecp256k1, algo) + } else { + require.EqualError(t, err, tt.expectedErr.Error()) + } + }) + } +} + func TestAltSigningAlgoList_Contains(t *testing.T) { list := AltSigningAlgoList{ AltSecp256k1, From 37056bdb860187bde5fbfe329302ba7fd9604f35 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 12:00:30 +0200 Subject: [PATCH 074/148] update context --- client/context/context.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/client/context/context.go b/client/context/context.go index 5e536251b0b..5a332c0d62f 100644 --- a/client/context/context.go +++ b/client/context/context.go @@ -25,7 +25,6 @@ type CLIContext struct { Client rpcclient.Client ChainID string Marshaler codec.Marshaler - Keybase keyring.Keybase Input io.Reader Output io.Writer OutputFormat string @@ -321,7 +320,7 @@ func GetFromFields(input io.Reader, from string, genOnly bool) (sdk.AccAddress, return addr, "", nil } - keybase, err := keyring.NewKeyring(sdk.KeyringServiceName(), + keybase, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), input) if err != nil { return nil, "", err @@ -329,12 +328,12 @@ func GetFromFields(input io.Reader, from string, genOnly bool) (sdk.AccAddress, var info keyring.Info if addr, err := sdk.AccAddressFromBech32(from); err == nil { - info, err = keybase.GetByAddress(addr) + info, err = keybase.KeyByAddress(addr) if err != nil { return nil, "", err } } else { - info, err = keybase.Get(from) + info, err = keybase.Key(from) if err != nil { return nil, "", err } From ad0284d6877b366d4aea08b76402a0b86682bb21 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 12:04:35 +0200 Subject: [PATCH 075/148] update factory tx --- client/tx/factory.go | 8 ++++---- client/tx/tx.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/tx/factory.go b/client/tx/factory.go index 4b05b2419a4..25cff13d672 100644 --- a/client/tx/factory.go +++ b/client/tx/factory.go @@ -21,7 +21,7 @@ type AccountRetriever interface { // Factory defines a client transaction factory that facilitates generating and // signing an application-specific transaction. type Factory struct { - keybase keyring.Keybase + keybase keyring.Keyring txGenerator Generator accountRetriever AccountRetriever accountNumber uint64 @@ -36,7 +36,7 @@ type Factory struct { } func NewFactoryFromCLI(input io.Reader) Factory { - kb, err := keyring.NewKeyring( + kb, err := keyring.New( sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), @@ -68,7 +68,7 @@ func (f Factory) AccountNumber() uint64 { return f.accountNumber } func (f Factory) Sequence() uint64 { return f.sequence } func (f Factory) Gas() uint64 { return f.gas } func (f Factory) GasAdjustment() float64 { return f.gasAdjustment } -func (f Factory) Keybase() keyring.Keybase { return f.keybase } +func (f Factory) Keybase() keyring.Keyring { return f.keybase } func (f Factory) ChainID() string { return f.chainID } func (f Factory) Memo() string { return f.memo } func (f Factory) Fees() sdk.Coins { return f.fees } @@ -126,7 +126,7 @@ func (f Factory) WithGasPrices(gasPrices string) Factory { } // WithKeybase returns a copy of the Factory with updated Keybase. -func (f Factory) WithKeybase(keybase keyring.Keybase) Factory { +func (f Factory) WithKeybase(keybase keyring.Keyring) Factory { f.keybase = keybase return f } diff --git a/client/tx/tx.go b/client/tx/tx.go index 21fa4c16ffe..8b300a661c1 100644 --- a/client/tx/tx.go +++ b/client/tx/tx.go @@ -329,7 +329,7 @@ func Sign(txf Factory, name, passphrase string, tx ClientTx) ([]byte, error) { return nil, err } - sigBytes, pubkey, err := txf.keybase.Sign(name, passphrase, signBytes) + sigBytes, pubkey, err := txf.keybase.Sign(name, signBytes) if err != nil { return nil, err } From 773342aeb8abba8e799f792235df0d84538857dc Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 12:09:59 +0200 Subject: [PATCH 076/148] update show --- client/keys/show.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/keys/show.go b/client/keys/show.go index c423caa1aae..11473aba407 100644 --- a/client/keys/show.go +++ b/client/keys/show.go @@ -57,7 +57,7 @@ consisting of all the keys provided by name and multisig threshold.`, func runShowCmd(cmd *cobra.Command, args []string) (err error) { var info keyring.Info - kb, err := keyring.NewKeyring(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), cmd.InOrStdin()) + kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), cmd.InOrStdin()) if err != nil { return err } @@ -142,15 +142,15 @@ func runShowCmd(cmd *cobra.Command, args []string) (err error) { return nil } -func fetchKey(kb keyring.Keybase, keyref string) (keyring.Info, error) { - info, err := kb.Get(keyref) +func fetchKey(kb keyring.Keyring, keyref string) (keyring.Info, error) { + info, err := kb.Key(keyref) if err != nil { accAddr, err := sdk.AccAddressFromBech32(keyref) if err != nil { return info, err } - info, err = kb.GetByAddress(accAddr) + info, err = kb.KeyByAddress(accAddr) if err != nil { return info, errors.New("key not found") } From 0b55fafe99f9a089cc2d2dc3f3aa4e168510d95c Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 12:15:20 +0200 Subject: [PATCH 077/148] update server init --- server/init.go | 6 +++--- server/init_test.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/server/init.go b/server/init.go index 054cdb46086..9b767eb73c0 100644 --- a/server/init.go +++ b/server/init.go @@ -24,10 +24,10 @@ func GenerateCoinKey() (sdk.AccAddress, string, error) { // GenerateSaveCoinKey returns the address of a public key, along with the secret // phrase to recover the private key. -func GenerateSaveCoinKey(keybase keyring.Keybase, keyName, keyPass string, overwrite bool) (sdk.AccAddress, string, error) { +func GenerateSaveCoinKey(keybase keyring.Keyring, keyName, keyPass string, overwrite bool) (sdk.AccAddress, string, error) { // ensure no overwrite if !overwrite { - _, err := keybase.Get(keyName) + _, err := keybase.Key(keyName) if err == nil { return sdk.AccAddress([]byte{}), "", fmt.Errorf( "key already exists, overwrite is disabled") @@ -35,7 +35,7 @@ func GenerateSaveCoinKey(keybase keyring.Keybase, keyName, keyPass string, overw } // generate a private key, with recovery phrase - info, secret, err := keybase.CreateMnemonic(keyName, keyring.English, keyPass, keyring.Secp256k1) + info, secret, err := keybase.NewMnemonic(keyName, keyring.English, keyring.AltSecp256k1) if err != nil { return sdk.AccAddress([]byte{}), "", err } diff --git a/server/init_test.go b/server/init_test.go index e51b88effde..0528f176d3e 100644 --- a/server/init_test.go +++ b/server/init_test.go @@ -26,14 +26,14 @@ func TestGenerateSaveCoinKey(t *testing.T) { dir, cleanup := tests.NewTestCaseDir(t) t.Cleanup(cleanup) - kb, err := keyring.NewKeyring(t.Name(), "test", dir, nil) + kb, err := keyring.New(t.Name(), "test", dir, nil) require.NoError(t, err) addr, mnemonic, err := server.GenerateSaveCoinKey(kb, "keyname", "012345678", false) require.NoError(t, err) // Test key was actually saved - info, err := kb.Get("keyname") + info, err := kb.Key("keyname") require.NoError(t, err) require.Equal(t, addr, info.GetAddress()) @@ -48,7 +48,7 @@ func TestGenerateSaveCoinKeyOverwriteFlag(t *testing.T) { dir, cleanup := tests.NewTestCaseDir(t) t.Cleanup(cleanup) - kb, err := keyring.NewKeyring(t.Name(), "test", dir, nil) + kb, err := keyring.New(t.Name(), "test", dir, nil) require.NoError(t, err) keyname := "justakey" From 8bcc106a5d7dd3ef1210de9a643e464230e37cf0 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 12:29:51 +0200 Subject: [PATCH 078/148] update tx builder --- x/auth/client/tx.go | 2 +- x/auth/types/txbuilder.go | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/x/auth/client/tx.go b/x/auth/client/tx.go index 09f3146e7cd..08b894a1441 100644 --- a/x/auth/client/tx.go +++ b/x/auth/client/tx.go @@ -182,7 +182,7 @@ func SignStdTx( var signedStdTx authtypes.StdTx - info, err := txBldr.Keybase().Get(name) + info, err := txBldr.Keybase().Key(name) if err != nil { return signedStdTx, err } diff --git a/x/auth/types/txbuilder.go b/x/auth/types/txbuilder.go index 2c2576841c4..41f33684be6 100644 --- a/x/auth/types/txbuilder.go +++ b/x/auth/types/txbuilder.go @@ -17,7 +17,7 @@ import ( // TxBuilder implements a transaction context created in SDK modules. type TxBuilder struct { txEncoder sdk.TxEncoder - keybase keyring.Keybase + keybase keyring.Keyring accountNumber uint64 sequence uint64 gas uint64 @@ -53,7 +53,7 @@ func NewTxBuilder( // NewTxBuilderFromCLI returns a new initialized TxBuilder with parameters from // the command line using Viper. func NewTxBuilderFromCLI(input io.Reader) TxBuilder { - kb, err := keyring.NewKeyring(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), input) + kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), input) if err != nil { panic(err) } @@ -90,7 +90,7 @@ func (bldr TxBuilder) Gas() uint64 { return bldr.gas } func (bldr TxBuilder) GasAdjustment() float64 { return bldr.gasAdjustment } // Keybase returns the keybase -func (bldr TxBuilder) Keybase() keyring.Keybase { return bldr.keybase } +func (bldr TxBuilder) Keybase() keyring.Keyring { return bldr.keybase } // SimulateAndExecute returns the option to simulate and then execute the transaction // using the gas from the simulation results @@ -149,7 +149,7 @@ func (bldr TxBuilder) WithGasPrices(gasPrices string) TxBuilder { } // WithKeybase returns a copy of the context with updated keybase. -func (bldr TxBuilder) WithKeybase(keybase keyring.Keybase) TxBuilder { +func (bldr TxBuilder) WithKeybase(keybase keyring.Keyring) TxBuilder { bldr.keybase = keybase return bldr } @@ -272,17 +272,17 @@ func (bldr TxBuilder) SignStdTx(name, passphrase string, stdTx StdTx, appendSig } // MakeSignature builds a StdSignature given keybase, key name, passphrase, and a StdSignMsg. -func MakeSignature(keybase keyring.Keybase, name, passphrase string, +func MakeSignature(keybase keyring.Keyring, name, passphrase string, msg StdSignMsg) (sig StdSignature, err error) { if keybase == nil { - keybase, err = keyring.NewKeyring(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), os.Stdin) + keybase, err = keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), os.Stdin) if err != nil { return } } - sigBytes, pubkey, err := keybase.Sign(name, passphrase, msg.Bytes()) + sigBytes, pubkey, err := keybase.Sign(name, msg.Bytes()) if err != nil { return } From 51e81eebf15a74c9ffaccf0255e22be18c3fbf8f Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 2 Apr 2020 15:51:40 +0200 Subject: [PATCH 079/148] Switch NewInMemory over new implementation --- crypto/keyring/altkeyring.go | 21 +++++++++++---------- crypto/keyring/keyring.go | 6 +++--- server/init.go | 7 ++----- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 49e0973930f..f244763852b 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -34,7 +34,7 @@ func New( switch backend { case BackendMemory: - panic("not implemented") + return NewInMemory(opts...), err case BackendTest: db, err = keyring.Open(lkbToKeyringConfig(appName, rootDir, nil, true)) case BackendFile: @@ -53,6 +53,15 @@ func New( return nil, err } + return newKeystore(db, opts...), nil +} + +type keystore struct { + db keyring.Keyring + options altKrOptions +} + +func newKeystore(kr keyring.Keyring, opts ...AltKeyringOption) keystore { // Default options for keybase options := altKrOptions{ supportedAlgos: AltSigningAlgoList{AltSecp256k1}, @@ -63,15 +72,7 @@ func New( optionFn(&options) } - return keystore{ - db: db, - options: options, - }, nil -} - -type keystore struct { - db keyring.Keyring - options altKrOptions + return keystore{kr, options} } func (ks keystore) ExportPubKeyArmor(uid string) (string, error) { diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 024b2562360..f4a5988df0f 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -134,7 +134,7 @@ func NewKeyring( switch backend { case BackendMemory: - return NewInMemory(opts...), nil + panic("not implemented") case BackendTest: db, err = keyring.Open(lkbToKeyringConfig(appName, rootDir, nil, true)) case BackendFile: @@ -158,8 +158,8 @@ func NewKeyring( // 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 ...KeybaseOption) Keybase { - return newKeyringKeybase(keyring.NewArrayKeyring(nil), opts...) +func NewInMemory(opts ...AltKeyringOption) Keyring { + return newKeystore(keyring.NewArrayKeyring(nil), opts...) } // CreateMnemonic generates a new key and persists it to storage, encrypted diff --git a/server/init.go b/server/init.go index 9b767eb73c0..cad2ed13088 100644 --- a/server/init.go +++ b/server/init.go @@ -11,15 +11,12 @@ import ( // GenerateCoinKey returns the address of a public key, along with the secret // phrase to recover the private key. func GenerateCoinKey() (sdk.AccAddress, string, error) { - // generate a private key, with recovery phrase - info, secret, err := keyring.NewInMemory().CreateMnemonic( - "name", keyring.English, "pass", keyring.Secp256k1) + info, secret, err := keyring.NewInMemory().NewMnemonic("name", keyring.English, keyring.AltSecp256k1) if err != nil { return sdk.AccAddress([]byte{}), "", err } - addr := info.GetPubKey().Address() - return sdk.AccAddress(addr), secret, nil + return sdk.AccAddress(info.GetPubKey().Address()), secret, nil } // GenerateSaveCoinKey returns the address of a public key, along with the secret From b68b0fdf82be86197792d0d48a626984c52e2aae Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 2 Apr 2020 15:54:57 +0200 Subject: [PATCH 080/148] Simplify tests --- client/keys/codec_test.go | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/client/keys/codec_test.go b/client/keys/codec_test.go index 7aca4510f95..33f6103d188 100644 --- a/client/keys/codec_test.go +++ b/client/keys/codec_test.go @@ -1,12 +1,12 @@ -package keys +package keys_test import ( - "fmt" - "reflect" + "bytes" "testing" "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/crypto/keyring" ) @@ -58,15 +58,9 @@ func TestMarshalJSON(t *testing.T) { for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { - got, err := MarshalJSON(tt.args.o) - if (err != nil) != tt.wantErr { - t.Errorf("MarshalJSON() error = %v, wantErr %v", err, tt.wantErr) - return - } - fmt.Printf("%s\n", got) - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("MarshalJSON() = %v, want %v", got, tt.want) - } + got, err := keys.MarshalJSON(tt.args.o) + require.Equal(t, tt.wantErr, err != nil) + require.True(t, bytes.Equal(got, tt.want)) }) } } @@ -94,10 +88,8 @@ func TestUnmarshalJSON(t *testing.T) { for idx, tt := range tests { idx, tt := idx, tt t.Run(tt.name, func(t *testing.T) { - if err := UnmarshalJSON(tt.args.bz, tt.args.ptr); (err != nil) != tt.wantErr { - t.Errorf("unmarshalJSON() error = %v, wantErr %v", err, tt.wantErr) - } - + err := keys.UnmarshalJSON(tt.args.bz, tt.args.ptr) + require.Equal(t, tt.wantErr, err != nil) // Confirm deserialized objects are the same require.Equal(t, data.Keys[idx], data.Answers[idx]) }) From 1abec0152b1ba9eda88613497fe8e3f72a8bf479 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 2 Apr 2020 17:02:42 +0200 Subject: [PATCH 081/148] Don't use infoKey with the new keyring --- crypto/keyring/altkeyring.go | 14 +++++--------- crypto/keyring/keyring.go | 4 ++-- crypto/keyring/types.go | 1 + 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index f244763852b..4db5b07d862 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -307,7 +307,7 @@ func (ks keystore) Delete(uid string) error { return err } - err = ks.db.Remove(string(infoKey(uid))) + err = ks.db.Remove(uid) if err != nil { return err } @@ -415,9 +415,7 @@ func (ks keystore) isSupportedSigningAlgo(algo AltSigningAlgo) bool { } func (ks keystore) Key(uid string) (Info, error) { - key := infoKey(uid) - - bs, err := ks.db.Get(string(key)) + bs, err := ks.db.Get(uid) if err != nil { return nil, err } @@ -442,13 +440,11 @@ func (ks keystore) writeLocalKey(name string, priv tmcrypto.PrivKey, algo pubKey return info, nil } -func (ks keystore) writeInfo(name string, info Info) error { +func (ks keystore) writeInfo(uid string, info Info) error { // write the info by key - key := infoKey(name) serializedInfo := marshalInfo(info) - err := ks.db.Set(keyring.Item{ - Key: string(key), + Key: uid, Data: serializedInfo, }) if err != nil { @@ -457,7 +453,7 @@ func (ks keystore) writeInfo(name string, info Info) error { err = ks.db.Set(keyring.Item{ Key: addrHexKeyAsString(info.GetAddress()), - Data: key, + Data: []byte(uid), }) if err != nil { return err diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index f4a5988df0f..eaaa50e4f8f 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -652,9 +652,9 @@ func newRealPrompt(dir string, buf io.Reader) func(string) (string, error) { } func addrHexKey(address types.Address) []byte { - return []byte(addrHexKeyAsString(address)) + return []byte(fmt.Sprintf("%s.%s", hex.EncodeToString(address.Bytes()), addressSuffix)) } func addrHexKeyAsString(address types.Address) string { - return fmt.Sprintf("%s.%s", hex.EncodeToString(address.Bytes()), addressSuffix) + return fmt.Sprintf("%s:%s", addressPrefix, hex.EncodeToString(address.Bytes())) } diff --git a/crypto/keyring/types.go b/crypto/keyring/types.go index 0e48d9cdbab..9fa9d4cee3e 100644 --- a/crypto/keyring/types.go +++ b/crypto/keyring/types.go @@ -34,6 +34,7 @@ const ( // bits of entropy to draw when creating a mnemonic defaultEntropySize = 256 addressSuffix = "address" + addressPrefix = "addr" infoSuffix = "info" ) From 6d8031fdb83b95772942d9cbc5f510a594a55fd0 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 2 Apr 2020 17:23:30 +0200 Subject: [PATCH 082/148] Fix server tests --- server/init_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/server/init_test.go b/server/init_test.go index 0528f176d3e..1828e2aedbb 100644 --- a/server/init_test.go +++ b/server/init_test.go @@ -6,8 +6,10 @@ import ( "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/crypto/keys/hd" "github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/tests" + "github.com/cosmos/cosmos-sdk/types" ) func TestGenerateCoinKey(t *testing.T) { @@ -16,7 +18,7 @@ func TestGenerateCoinKey(t *testing.T) { require.NoError(t, err) // Test creation - info, err := keyring.NewInMemory().CreateAccount("xxx", mnemonic, "", "012345678", keyring.CreateHDPath(0, 0).String(), keyring.Secp256k1) + info, err := keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), keyring.AltSecp256k1) require.NoError(t, err) require.Equal(t, addr, info.GetAddress()) } @@ -38,7 +40,7 @@ func TestGenerateSaveCoinKey(t *testing.T) { require.Equal(t, addr, info.GetAddress()) // Test in-memory recovery - info, err = keyring.NewInMemory().CreateAccount("xxx", mnemonic, "", "012345678", keyring.CreateHDPath(0, 0).String(), keyring.Secp256k1) + info, err = keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), keyring.AltSecp256k1) require.NoError(t, err) require.Equal(t, addr, info.GetAddress()) } From d8e4640965dca7635f3c952008026400f4a66be4 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 2 Apr 2020 17:56:03 +0200 Subject: [PATCH 083/148] Revert "Don't use infoKey with the new keyring" This reverts commit 1abec0152b1ba9eda88613497fe8e3f72a8bf479. --- crypto/keyring/altkeyring.go | 14 +++++++++----- crypto/keyring/keyring.go | 4 ++-- crypto/keyring/types.go | 1 - 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 4db5b07d862..f244763852b 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -307,7 +307,7 @@ func (ks keystore) Delete(uid string) error { return err } - err = ks.db.Remove(uid) + err = ks.db.Remove(string(infoKey(uid))) if err != nil { return err } @@ -415,7 +415,9 @@ func (ks keystore) isSupportedSigningAlgo(algo AltSigningAlgo) bool { } func (ks keystore) Key(uid string) (Info, error) { - bs, err := ks.db.Get(uid) + key := infoKey(uid) + + bs, err := ks.db.Get(string(key)) if err != nil { return nil, err } @@ -440,11 +442,13 @@ func (ks keystore) writeLocalKey(name string, priv tmcrypto.PrivKey, algo pubKey return info, nil } -func (ks keystore) writeInfo(uid string, info Info) error { +func (ks keystore) writeInfo(name string, info Info) error { // write the info by key + key := infoKey(name) serializedInfo := marshalInfo(info) + err := ks.db.Set(keyring.Item{ - Key: uid, + Key: string(key), Data: serializedInfo, }) if err != nil { @@ -453,7 +457,7 @@ func (ks keystore) writeInfo(uid string, info Info) error { err = ks.db.Set(keyring.Item{ Key: addrHexKeyAsString(info.GetAddress()), - Data: []byte(uid), + Data: key, }) if err != nil { return err diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index eaaa50e4f8f..f4a5988df0f 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -652,9 +652,9 @@ func newRealPrompt(dir string, buf io.Reader) func(string) (string, error) { } func addrHexKey(address types.Address) []byte { - return []byte(fmt.Sprintf("%s.%s", hex.EncodeToString(address.Bytes()), addressSuffix)) + return []byte(addrHexKeyAsString(address)) } func addrHexKeyAsString(address types.Address) string { - return fmt.Sprintf("%s:%s", addressPrefix, hex.EncodeToString(address.Bytes())) + return fmt.Sprintf("%s.%s", hex.EncodeToString(address.Bytes()), addressSuffix) } diff --git a/crypto/keyring/types.go b/crypto/keyring/types.go index 9fa9d4cee3e..0e48d9cdbab 100644 --- a/crypto/keyring/types.go +++ b/crypto/keyring/types.go @@ -34,7 +34,6 @@ const ( // bits of entropy to draw when creating a mnemonic defaultEntropySize = 256 addressSuffix = "address" - addressPrefix = "addr" infoSuffix = "info" ) From c53a452a4f67db366f3003216eab3b44a80e2c77 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 2 Apr 2020 18:30:20 +0200 Subject: [PATCH 084/148] Fix tests --- crypto/keyring/altkeyring_test.go | 37 +- crypto/keyring/keyring_test.go | 2025 +++++++++++++++-------------- 2 files changed, 1041 insertions(+), 1021 deletions(-) diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 9dfe0e5bd07..500785bcc2b 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -4,16 +4,15 @@ import ( "fmt" "testing" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/multisig" + "github.com/cosmos/go-bip39" + "github.com/cosmos/cosmos-sdk/tests" "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/go-bip39" ) const ( @@ -96,13 +95,33 @@ func TestAltKeyring_SaveLedgerKey(t *testing.T) { _, err = keyring.SaveLedgerKey("key", notSupportedAlgo{}, "cosmos", 0, 0) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) - info, err := keyring.SaveLedgerKey("key", AltSecp256k1, "cosmos", 0, 0) + ledger, err := keyring.SaveLedgerKey("some_account", AltSecp256k1, "cosmos", 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") return } - require.Equal(t, "key", info.GetName()) + // The mock is available, check that the address is correct + require.Equal(t, "some_account", ledger.GetName()) + pubKey := ledger.GetPubKey() + pk, err := types.Bech32ifyPubKey(types.Bech32PubKeyTypeAccPub, pubKey) + require.NoError(t, err) + require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) + + // Check that restoring the key gets the same results + restoredKey, err := keyring.Key("some_account") + require.NoError(t, err) + require.NotNil(t, restoredKey) + require.Equal(t, "some_account", restoredKey.GetName()) + require.Equal(t, TypeLedger, restoredKey.GetType()) + pubKey = restoredKey.GetPubKey() + pk, err = types.Bech32ifyPubKey(types.Bech32PubKeyTypeAccPub, pubKey) + require.NoError(t, err) + require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) + + path, err := restoredKey.GetPath() + require.NoError(t, err) + require.Equal(t, "44'/118'/3'/0/1", path.String()) } func TestAltKeyring_Get(t *testing.T) { @@ -297,7 +316,7 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { require.EqualError(t, err, "failed to decrypt private key: ciphertext decryption failed") err = keyring.ImportPrivKey(newUID, armor, passphrase) - assert.NoError(t, err) + require.NoError(t, err) } func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { @@ -325,7 +344,7 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { require.EqualError(t, err, "failed to decrypt private key: ciphertext decryption failed") err = keyring.ImportPrivKey(newUID, armor, passphrase) - assert.NoError(t, err) + require.NoError(t, err) } func TestAltKeyring_ImportExportPubKey(t *testing.T) { @@ -348,7 +367,7 @@ func TestAltKeyring_ImportExportPubKey(t *testing.T) { newUID := otherID err = keyring.ImportPubKey(newUID, armor) - assert.NoError(t, err) + require.NoError(t, err) } func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { @@ -371,7 +390,7 @@ func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { newUID := otherID err = keyring.ImportPubKey(newUID, armor) - assert.NoError(t, err) + require.NoError(t, err) } func TestAltKeyring_ConstructorSupportedAlgos(t *testing.T) { diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index d57875edcb4..076172de84a 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -1,1014 +1,1015 @@ package keyring -import ( - "bytes" - "errors" - "fmt" - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/tendermint/go-amino" - tmcrypto "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/crypto/ed25519" - tmamino "github.com/tendermint/tendermint/crypto/encoding/amino" - "github.com/tendermint/tendermint/crypto/multisig" - "github.com/tendermint/tendermint/crypto/secp256k1" - - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/crypto" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" - "github.com/cosmos/cosmos-sdk/tests" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -func init() { - crypto.BcryptSecurityParameter = 1 -} - -const ( - nums = "1234" - foobar = "foobar" -) - -func TestNewKeyring(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - mockIn := strings.NewReader("") - t.Cleanup(cleanup) - kr, err := NewKeyring("cosmos", BackendFile, dir, mockIn) - require.NoError(t, err) - - mockIn.Reset("password\npassword\n") - info, _, err := kr.CreateMnemonic("foo", English, "password", Secp256k1) - require.NoError(t, err) - require.Equal(t, "foo", info.GetName()) -} - -func TestKeyManagementKeyRing(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - kb, err := NewKeyring("keybasename", "test", dir, nil) - require.NoError(t, err) - - algo := Secp256k1 - n1, n2, n3 := "personal", "business", "other" - p1, p2 := "1234", "really-secure!@#$" - - // Check empty state - l, err := kb.List() - require.Nil(t, err) - assert.Empty(t, l) - - _, _, err = kb.CreateMnemonic(n1, English, p1, Ed25519) - require.Error(t, err, "ed25519 keys are currently not supported by keybase") - - // create some keys - _, err = kb.Get(n1) - require.Error(t, err) - i, _, err := kb.CreateMnemonic(n1, English, p1, algo) - - require.NoError(t, err) - require.Equal(t, n1, i.GetName()) - _, _, err = kb.CreateMnemonic(n2, English, p2, algo) - require.NoError(t, err) - - // we can get these keys - i2, err := kb.Get(n2) - require.NoError(t, err) - _, err = kb.Get(n3) - require.NotNil(t, err) - _, err = kb.GetByAddress(accAddr(i2)) - require.NoError(t, err) - addr, err := sdk.AccAddressFromBech32("cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t") - require.NoError(t, err) - _, err = kb.GetByAddress(addr) - require.NotNil(t, err) - - // list shows them in order - keyS, err := kb.List() - require.NoError(t, err) - require.Equal(t, 2, len(keyS)) - // note these are in alphabetical order - require.Equal(t, n2, keyS[0].GetName()) - require.Equal(t, n1, keyS[1].GetName()) - require.Equal(t, i2.GetPubKey(), keyS[0].GetPubKey()) - - // deleting a key removes it - err = kb.Delete("bad name", "foo", false) - require.NotNil(t, err) - err = kb.Delete(n1, p1, false) - require.NoError(t, err) - keyS, err = kb.List() - require.NoError(t, err) - require.Equal(t, 1, len(keyS)) - _, err = kb.Get(n1) - require.Error(t, err) - - // create an offline key - o1 := "offline" - priv1 := ed25519.GenPrivKey() - pub1 := priv1.PubKey() - i, err = kb.CreateOffline(o1, pub1, Ed25519) - require.Nil(t, err) - require.Equal(t, pub1, i.GetPubKey()) - require.Equal(t, o1, i.GetName()) - keyS, err = kb.List() - require.NoError(t, err) - require.Equal(t, 2, len(keyS)) - - // delete the offline key - err = kb.Delete(o1, "", false) - require.NoError(t, err) - keyS, err = kb.List() - require.NoError(t, err) - require.Equal(t, 1, len(keyS)) - - // addr cache gets nuked - and test skip flag - require.NoError(t, kb.Delete(n2, "", true)) -} - -// TestSignVerify does some detailed checks on how we sign and validate -// signatures -func TestSignVerifyKeyRingWithLedger(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - kb, err := NewKeyring("keybasename", "test", dir, nil) - require.NoError(t, err) - - i1, err := kb.CreateLedger("key", Secp256k1, "cosmos", 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()) - - p1 := "1234" - d1 := []byte("my first message") - s1, pub1, err := kb.Sign("key", p1, d1) - require.NoError(t, err) - - s2, pub2, err := SignWithLedger(i1, d1) - require.NoError(t, err) - - require.Equal(t, i1.GetPubKey(), pub1) - require.Equal(t, i1.GetPubKey(), pub2) - require.True(t, pub1.VerifyBytes(d1, s1)) - require.True(t, i1.GetPubKey().VerifyBytes(d1, s1)) - require.True(t, bytes.Equal(s1, s2)) - - localInfo, _, err := kb.CreateMnemonic("test", English, p1, Secp256k1) - require.NoError(t, err) - _, _, err = SignWithLedger(localInfo, d1) - require.Error(t, err) - require.Equal(t, "not a ledger object", err.Error()) -} - -func TestSignVerifyKeyRing(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - kb, err := NewKeyring("keybasename", "test", dir, nil) - require.NoError(t, err) - algo := Secp256k1 - - n1, n2, n3 := "some dude", "a dudette", "dude-ish" - p1, p2, p3 := "1234", "foobar", "foobar" - - // create two users and get their info - i1, _, err := kb.CreateMnemonic(n1, English, p1, algo) - require.Nil(t, err) - - i2, _, err := kb.CreateMnemonic(n2, English, p2, algo) - require.Nil(t, err) - - // Import a public key - armor, err := kb.ExportPubKey(n2) - require.Nil(t, err) - err = kb.ImportPubKey(n3, armor) - require.NoError(t, err) - i3, err := kb.Get(n3) - require.NoError(t, err) - require.Equal(t, i3.GetName(), n3) - - // let's try to sign some messages - d1 := []byte("my first message") - d2 := []byte("some other important info!") - d3 := []byte("feels like I forgot something...") - - // try signing both data with both .. - s11, pub1, err := kb.Sign(n1, p1, d1) - require.Nil(t, err) - require.Equal(t, i1.GetPubKey(), pub1) - - s12, pub1, err := kb.Sign(n1, p1, d2) - require.Nil(t, err) - require.Equal(t, i1.GetPubKey(), pub1) - - s21, pub2, err := kb.Sign(n2, p2, d1) - require.Nil(t, err) - require.Equal(t, i2.GetPubKey(), pub2) - - s22, pub2, err := kb.Sign(n2, p2, d2) - require.Nil(t, err) - require.Equal(t, i2.GetPubKey(), pub2) - - // let's try to validate and make sure it only works when everything is proper - cases := []struct { - key tmcrypto.PubKey - data []byte - sig []byte - valid bool - }{ - // proper matches - {i1.GetPubKey(), d1, s11, true}, - // change data, pubkey, or signature leads to fail - {i1.GetPubKey(), d2, s11, false}, - {i2.GetPubKey(), d1, s11, false}, - {i1.GetPubKey(), d1, s21, false}, - // make sure other successes - {i1.GetPubKey(), d2, s12, true}, - {i2.GetPubKey(), d1, s21, true}, - {i2.GetPubKey(), d2, s22, true}, - } - - for i, tc := range cases { - valid := tc.key.VerifyBytes(tc.data, tc.sig) - require.Equal(t, tc.valid, valid, "%d", i) - } - - // Now try to sign data with a secret-less key - _, _, err = kb.Sign(n3, p3, d3) - require.Error(t, err) - require.Equal(t, "cannot sign with offline keys", err.Error()) -} - -func TestExportImportKeyRing(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - kb, err := NewKeyring("keybasename", "test", dir, nil) - require.NoError(t, err) - - info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1) - require.NoError(t, err) - require.Equal(t, info.GetName(), "john") - - john, err := kb.Get("john") - require.NoError(t, err) - require.Equal(t, info.GetName(), "john") - johnAddr := info.GetPubKey().Address() - - armor, err := kb.Export("john") - require.NoError(t, err) - - err = kb.Import("john2", armor) - require.NoError(t, err) - - john2, err := kb.Get("john2") - require.NoError(t, err) - - require.Equal(t, john.GetPubKey().Address(), johnAddr) - require.Equal(t, john.GetName(), "john") - require.Equal(t, john, john2) -} - -func TestExportImportPubKeyKeyRing(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - kb, err := NewKeyring("keybasename", "test", dir, nil) - require.NoError(t, err) - algo := Secp256k1 - - // CreateMnemonic a private-public key pair and ensure consistency - notPasswd := "n9y25ah7" - info, _, err := kb.CreateMnemonic("john", English, notPasswd, algo) - require.Nil(t, err) - require.NotEqual(t, info, "") - require.Equal(t, info.GetName(), "john") - addr := info.GetPubKey().Address() - john, err := kb.Get("john") - require.NoError(t, err) - require.Equal(t, john.GetName(), "john") - require.Equal(t, john.GetPubKey().Address(), addr) - - // Export the public key only - armor, err := kb.ExportPubKey("john") - require.NoError(t, err) - // Import it under a different name - err = kb.ImportPubKey("john-pubkey-only", armor) - require.NoError(t, err) - // Ensure consistency - john2, err := kb.Get("john-pubkey-only") - require.NoError(t, err) - // Compare the public keys - require.True(t, john.GetPubKey().Equals(john2.GetPubKey())) - // Ensure the original key hasn't changed - john, err = kb.Get("john") - require.NoError(t, err) - require.Equal(t, john.GetPubKey().Address(), addr) - require.Equal(t, john.GetName(), "john") - - // Ensure keys cannot be overwritten - err = kb.ImportPubKey("john-pubkey-only", armor) - require.NotNil(t, err) -} - -func TestExportPrivateKeyObjectKeyRing(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - kb, err := NewKeyring("keybasename", "test", dir, nil) - require.NoError(t, err) - - info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1) - require.NoError(t, err) - require.Equal(t, info.GetName(), "john") - - // export private key object - exported, err := kb.ExportPrivateKeyObject("john", "secretcpw") - require.Nil(t, err, "%+v", err) - require.True(t, exported.PubKey().Equals(info.GetPubKey())) -} - -func TestAdvancedKeyManagementKeyRing(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - kb, err := NewKeyring("keybasename", "test", dir, nil) - require.NoError(t, err) - - algo := Secp256k1 - n1, n2 := "old-name", "new name" - p1 := "1234" - - // make sure key works with initial password - _, _, err = kb.CreateMnemonic(n1, English, p1, algo) - require.Nil(t, err, "%+v", err) - - _, err = kb.Export(n1 + ".notreal") - require.NotNil(t, err) - _, err = kb.Export(" " + n1) - require.NotNil(t, err) - _, err = kb.Export(n1 + " ") - require.NotNil(t, err) - _, err = kb.Export("") - require.NotNil(t, err) - exported, err := kb.Export(n1) - require.Nil(t, err, "%+v", err) - - // import succeeds - err = kb.Import(n2, exported) - require.NoError(t, err) - - // second import fails - err = kb.Import(n2, exported) - require.NotNil(t, err) -} - -func TestSeedPhraseKeyRing(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - kb, err := NewKeyring("keybasename", "test", dir, nil) - require.NoError(t, err) - - algo := Secp256k1 - n1, n2 := "lost-key", "found-again" - p1, p2 := "1234", "foobar" - - // make sure key works with initial password - info, mnemonic, err := kb.CreateMnemonic(n1, English, p1, algo) - require.Nil(t, err, "%+v", err) - require.Equal(t, n1, info.GetName()) - assert.NotEmpty(t, mnemonic) - - // now, let us delete this key - err = kb.Delete(n1, p1, false) - require.Nil(t, err, "%+v", err) - _, err = kb.Get(n1) - require.NotNil(t, err) - - // let us re-create it from the mnemonic-phrase - params := *hd.NewFundraiserParams(0, sdk.CoinType, 0) - hdPath := params.String() - newInfo, err := kb.CreateAccount(n2, mnemonic, DefaultBIP39Passphrase, p2, hdPath, Secp256k1) - require.NoError(t, err) - require.Equal(t, n2, newInfo.GetName()) - require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) - require.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) -} - -func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - kb, err := NewKeyring("keybasename", "test", dir, nil) - require.NoError(t, err) - _, _, err = kb.CreateMnemonic("john", English, "password", Secp256k1) - require.NoError(t, err) - - // no error, password is irrelevant, keystr cointains ASCII armored private key - keystr, err := kb.ExportPrivKey("john", "wrongpassword", "password") - require.NoError(t, err) - require.NotEmpty(t, keystr) - - // try import the key - wrong password - err = kb.ImportPrivKey("john2", keystr, "somepassword") - require.Equal(t, "failed to decrypt private key: ciphertext decryption failed", err.Error()) - - // try import the key with the correct password - require.NoError(t, kb.ImportPrivKey("john2", keystr, "password")) - - // overwrite is not allowed - err = kb.ImportPrivKey("john2", keystr, "password") - require.Equal(t, "cannot overwrite key: john2", err.Error()) - - // try export non existing key - _, err = kb.ExportPrivKey("john3", "wrongpassword", "password") - require.Equal(t, "The specified item could not be found in the keyring", err.Error()) -} - -func TestSupportedAlgos(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - kb, err := NewKeyring("keybasename", "test", dir, nil) - require.NoError(t, err) - require.Equal(t, []pubKeyType{"secp256k1"}, kb.SupportedAlgos()) - require.Equal(t, []pubKeyType{"secp256k1"}, kb.SupportedAlgosLedger()) -} - -func TestCustomDerivFuncKey(t *testing.T) { - kb := NewInMemory(WithDeriveFunc(func(mnemonic string, bip39Passphrase, hdPath string, algo pubKeyType) ([]byte, error) { - return nil, errors.New("cannot derive keys") - })) - _, _, err := kb.CreateMnemonic("test", English, "", "") - require.Error(t, err, "cannot derive keys") -} - -func TestInMemoryLanguage(t *testing.T) { - kb := NewInMemory() - _, _, err := kb.CreateMnemonic("something", Japanese, "no_pass", Secp256k1) - require.Error(t, err) - require.Equal(t, "unsupported language: only english is supported", err.Error()) -} - -func TestInMemoryCreateMultisig(t *testing.T) { - kb, err := NewKeyring("keybasename", "memory", "", nil) - require.NoError(t, err) - multi := multisig.PubKeyMultisigThreshold{ - K: 1, - PubKeys: []tmcrypto.PubKey{secp256k1.GenPrivKey().PubKey()}, - } - _, err = kb.CreateMulti("multi", multi) - require.NoError(t, err) -} - -func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { - kb := NewInMemory() - _, err := kb.CreateAccount( - "some_account", - "malarkey pair crucial catch public canyon evil outer stage ten gym tornado", - "", "", CreateHDPath(0, 0).String(), Secp256k1) - require.Error(t, err) - require.Equal(t, "Invalid mnemonic", err.Error()) -} - -func TestInMemoryCreateLedgerUnsupportedAlgo(t *testing.T) { - kb := NewInMemory() - - supportedLedgerAlgos := kb.SupportedAlgosLedger() - for _, supportedAlgo := range supportedLedgerAlgos { - if Ed25519 == supportedAlgo { - require.FailNow(t, "Was not an unsupported algorithm") - } - } - - _, err := kb.CreateLedger("some_account", Ed25519, "cosmos", 0, 1) - require.Error(t, err) - require.Equal(t, "unsupported signing algo", err.Error()) -} - -func TestInMemoryCreateLedger(t *testing.T) { - kb := NewInMemory(WithSupportedAlgosLedger([]pubKeyType{Secp256k1, Ed25519})) - - // test_cover and test_unit will result in different answers - // test_cover does not compile some dependencies so ledger is disabled - // test_unit may add a ledger mock - // both cases are acceptable - supportedLedgerAlgos := kb.SupportedAlgosLedger() - secpSupported := false - edSupported := false - for _, supportedAlgo := range supportedLedgerAlgos { - secpSupported = secpSupported || (supportedAlgo == Secp256k1) - edSupported = edSupported || (supportedAlgo == Ed25519) - } - require.True(t, secpSupported) - require.True(t, edSupported) - - ledger, err := kb.CreateLedger("some_account", Secp256k1, "cosmos", 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) - 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() - pk, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) - require.NoError(t, err) - require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) - - // Check that restoring the key gets the same results - restoredKey, err := kb.Get("some_account") - require.NoError(t, err) - require.NotNil(t, restoredKey) - require.Equal(t, "some_account", restoredKey.GetName()) - require.Equal(t, TypeLedger, restoredKey.GetType()) - pubKey = restoredKey.GetPubKey() - pk, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) - require.NoError(t, err) - require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) - - path, err := restoredKey.GetPath() - require.NoError(t, err) - require.Equal(t, "44'/118'/3'/0/1", path.String()) -} - -// TestInMemoryKeyManagement makes sure we can manipulate these keys well -func TestInMemoryKeyManagement(t *testing.T) { - // make the storage with reasonable defaults - cstore := NewInMemory(WithSupportedAlgos([]pubKeyType{Secp256k1, Sr25519})) - - // Test modified supported algos - supportedAlgos := cstore.SupportedAlgos() - secpSupported := false - edSupported := false - srSupported := false - for _, supportedAlgo := range supportedAlgos { - secpSupported = secpSupported || (supportedAlgo == Secp256k1) - edSupported = edSupported || (supportedAlgo == Ed25519) - srSupported = srSupported || (supportedAlgo == Sr25519) - } - require.True(t, secpSupported) - require.False(t, edSupported) - require.True(t, srSupported) - - algo := Secp256k1 - n1, n2, n3 := "personal", "business", "other" - p1, p2 := nums, "really-secure!@#$" - - // Check empty state - l, err := cstore.List() - require.Nil(t, err) - require.Empty(t, l) - - _, _, err = cstore.CreateMnemonic(n1, English, p1, Ed25519) - require.Error(t, err, "ed25519 keys are currently not supported by keybase") - - // create some keys - _, err = cstore.Get(n1) - require.Error(t, err) - i, _, err := cstore.CreateMnemonic(n1, English, p1, algo) - - require.NoError(t, err) - require.Equal(t, n1, i.GetName()) - _, _, err = cstore.CreateMnemonic(n2, English, p2, algo) - require.NoError(t, err) - - // we can get these keys - i2, err := cstore.Get(n2) - require.NoError(t, err) - _, err = cstore.Get(n3) - require.NotNil(t, err) - _, err = cstore.GetByAddress(accAddr(i2)) - require.NoError(t, err) - addr, err := sdk.AccAddressFromBech32("cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t") - require.NoError(t, err) - _, err = cstore.GetByAddress(addr) - require.NotNil(t, err) - - // list shows them in order - keyS, err := cstore.List() - require.NoError(t, err) - require.Equal(t, 2, len(keyS)) - // note these are in alphabetical order - require.Equal(t, n2, keyS[0].GetName()) - require.Equal(t, n1, keyS[1].GetName()) - require.Equal(t, i2.GetPubKey(), keyS[0].GetPubKey()) - - // deleting a key removes it - err = cstore.Delete("bad name", "foo", false) - require.NotNil(t, err) - err = cstore.Delete(n1, p1, false) - require.NoError(t, err) - keyS, err = cstore.List() - require.NoError(t, err) - require.Equal(t, 1, len(keyS)) - _, err = cstore.Get(n1) - require.Error(t, err) - - // create an offline key - o1 := "offline" - priv1 := ed25519.GenPrivKey() - pub1 := priv1.PubKey() - i, err = cstore.CreateOffline(o1, pub1, algo) - require.Nil(t, err) - require.Equal(t, pub1, i.GetPubKey()) - require.Equal(t, o1, i.GetName()) - iOffline := i.(*offlineInfo) - require.Equal(t, algo, iOffline.GetAlgo()) - keyS, err = cstore.List() - require.NoError(t, err) - require.Equal(t, 2, len(keyS)) - - // delete the offline key - err = cstore.Delete(o1, "", false) - require.NoError(t, err) - keyS, err = cstore.List() - require.NoError(t, err) - require.Equal(t, 1, len(keyS)) - - // addr cache gets nuked - and test skip flag - err = cstore.Delete(n2, "", true) - require.NoError(t, err) -} - -// TestInMemorySignVerify does some detailed checks on how we sign and validate -// signatures -func TestInMemorySignVerify(t *testing.T) { - cstore := NewInMemory() - algo := Secp256k1 - - n1, n2, n3 := "some dude", "a dudette", "dude-ish" - p1, p2, p3 := nums, foobar, foobar - - // create two users and get their info - i1, _, err := cstore.CreateMnemonic(n1, English, p1, algo) - require.Nil(t, err) - - i2, _, err := cstore.CreateMnemonic(n2, English, p2, algo) - require.Nil(t, err) - - // Import a public key - armor, err := cstore.ExportPubKey(n2) - require.Nil(t, err) - err = cstore.ImportPubKey(n3, armor) - require.NoError(t, err) - i3, err := cstore.Get(n3) - require.NoError(t, err) - require.Equal(t, i3.GetName(), n3) - - // let's try to sign some messages - d1 := []byte("my first message") - d2 := []byte("some other important info!") - d3 := []byte("feels like I forgot something...") - - // try signing both data with both .. - s11, pub1, err := cstore.Sign(n1, p1, d1) - require.Nil(t, err) - require.Equal(t, i1.GetPubKey(), pub1) - - s12, pub1, err := cstore.Sign(n1, p1, d2) - require.Nil(t, err) - require.Equal(t, i1.GetPubKey(), pub1) - - s21, pub2, err := cstore.Sign(n2, p2, d1) - require.Nil(t, err) - require.Equal(t, i2.GetPubKey(), pub2) - - s22, pub2, err := cstore.Sign(n2, p2, d2) - require.Nil(t, err) - require.Equal(t, i2.GetPubKey(), pub2) - - // let's try to validate and make sure it only works when everything is proper - cases := []struct { - key tmcrypto.PubKey - data []byte - sig []byte - valid bool - }{ - // proper matches - {i1.GetPubKey(), d1, s11, true}, - // change data, pubkey, or signature leads to fail - {i1.GetPubKey(), d2, s11, false}, - {i2.GetPubKey(), d1, s11, false}, - {i1.GetPubKey(), d1, s21, false}, - // make sure other successes - {i1.GetPubKey(), d2, s12, true}, - {i2.GetPubKey(), d1, s21, true}, - {i2.GetPubKey(), d2, s22, true}, - } - - for i, tc := range cases { - valid := tc.key.VerifyBytes(tc.data, tc.sig) - require.Equal(t, tc.valid, valid, "%d", i) - } - - // Now try to sign data with a secret-less key - _, _, err = cstore.Sign(n3, p3, d3) - require.Error(t, err) - require.Equal(t, "cannot sign with offline keys", err.Error()) -} - -// TestInMemoryExportImport tests exporting and importing -func TestInMemoryExportImport(t *testing.T) { - // make the storage with reasonable defaults - cstore := NewInMemory() - - info, _, err := cstore.CreateMnemonic("john", English, "secretcpw", Secp256k1) - require.NoError(t, err) - require.Equal(t, info.GetName(), "john") - - john, err := cstore.Get("john") - require.NoError(t, err) - require.Equal(t, info.GetName(), "john") - johnAddr := info.GetPubKey().Address() - - armor, err := cstore.Export("john") - require.NoError(t, err) - - err = cstore.Import("john2", armor) - require.NoError(t, err) - - john2, err := cstore.Get("john2") - require.NoError(t, err) - - require.Equal(t, john.GetPubKey().Address(), johnAddr) - require.Equal(t, john.GetName(), "john") - require.Equal(t, john, john2) -} - -func TestInMemoryExportImportPrivKey(t *testing.T) { - kb := NewInMemory() - - info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1) - require.NoError(t, err) - require.Equal(t, info.GetName(), "john") - priv1, err := kb.Get("john") - require.NoError(t, err) - - // decrypt local private key, and produce encrypted ASCII armored output - armored, err := kb.ExportPrivKey("john", "secretcpw", "new_secretcpw") - require.NoError(t, err) - - // delete exported key - require.NoError(t, kb.Delete("john", "", true)) - _, err = kb.Get("john") - require.Error(t, err) - - // import armored key - require.NoError(t, kb.ImportPrivKey("john", armored, "new_secretcpw")) - - // ensure old and new keys match - priv2, err := kb.Get("john") - require.NoError(t, err) - require.True(t, priv1.GetPubKey().Equals(priv2.GetPubKey())) -} - -func TestInMemoryExportImportPubKey(t *testing.T) { - // make the storage with reasonable defaults - cstore := NewInMemory() - - // CreateMnemonic a private-public key pair and ensure consistency - notPasswd := "n9y25ah7" - info, _, err := cstore.CreateMnemonic("john", English, notPasswd, Secp256k1) - require.Nil(t, err) - require.NotEqual(t, info, "") - require.Equal(t, info.GetName(), "john") - addr := info.GetPubKey().Address() - john, err := cstore.Get("john") - require.NoError(t, err) - require.Equal(t, john.GetName(), "john") - require.Equal(t, john.GetPubKey().Address(), addr) - - // Export the public key only - armor, err := cstore.ExportPubKey("john") - require.NoError(t, err) - // Import it under a different name - err = cstore.ImportPubKey("john-pubkey-only", armor) - require.NoError(t, err) - // Ensure consistency - john2, err := cstore.Get("john-pubkey-only") - require.NoError(t, err) - // Compare the public keys - require.True(t, john.GetPubKey().Equals(john2.GetPubKey())) - // Ensure the original key hasn't changed - john, err = cstore.Get("john") - require.NoError(t, err) - require.Equal(t, john.GetPubKey().Address(), addr) - require.Equal(t, john.GetName(), "john") - - // Ensure keys cannot be overwritten - err = cstore.ImportPubKey("john-pubkey-only", armor) - require.NotNil(t, err) -} - -func TestInMemoryExportPrivateKeyObject(t *testing.T) { - kb := NewInMemory() - - info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1) - require.NoError(t, err) - require.Equal(t, info.GetName(), "john") - - // export private key object - _, err = kb.ExportPrivateKeyObject("john", "invalid") - require.NoError(t, err, "%+v", err) - exported, err := kb.ExportPrivateKeyObject("john", "secretcpw") - require.Nil(t, err, "%+v", err) - require.True(t, exported.PubKey().Equals(info.GetPubKey())) -} - -// TestInMemoryAdvancedKeyManagement verifies update, import, export functionality -func TestInMemoryAdvancedKeyManagement(t *testing.T) { - // make the storage with reasonable defaults - cstore := NewInMemory() - - algo := Secp256k1 - n1, n2 := "old-name", "new name" - p1 := nums - - // make sure key works with initial password - _, _, err := cstore.CreateMnemonic(n1, English, p1, algo) - require.Nil(t, err, "%+v", err) - - // exporting requires the proper name and passphrase - _, err = cstore.Export(n1 + ".notreal") - require.NotNil(t, err) - _, err = cstore.Export(" " + n1) - require.NotNil(t, err) - _, err = cstore.Export(n1 + " ") - require.NotNil(t, err) - _, err = cstore.Export("") - require.NotNil(t, err) - exported, err := cstore.Export(n1) - require.Nil(t, err, "%+v", err) - - // import succeeds - err = cstore.Import(n2, exported) - require.NoError(t, err) - - // second import fails - err = cstore.Import(n2, exported) - require.NotNil(t, err) -} - -// TestInMemorySeedPhrase verifies restoring from a seed phrase -func TestInMemorySeedPhrase(t *testing.T) { - - // make the storage with reasonable defaults - cstore := NewInMemory() - - algo := Secp256k1 - n1, n2 := "lost-key", "found-again" - p1, p2 := nums, foobar - - // make sure key works with initial password - info, mnemonic, err := cstore.CreateMnemonic(n1, English, p1, algo) - require.Nil(t, err, "%+v", err) - require.Equal(t, n1, info.GetName()) - require.NotEmpty(t, mnemonic) - - // now, let us delete this key - err = cstore.Delete(n1, p1, false) - require.Nil(t, err, "%+v", err) - _, err = cstore.Get(n1) - require.NotNil(t, err) - - // let us re-create it from the mnemonic-phrase - params := *hd.NewFundraiserParams(0, sdk.CoinType, 0) - hdPath := params.String() - newInfo, err := cstore.CreateAccount(n2, mnemonic, DefaultBIP39Passphrase, p2, hdPath, Secp256k1) - require.NoError(t, err) - require.Equal(t, n2, newInfo.GetName()) - require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) - require.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) -} - -func ExampleNew() { - // Select the encryption and storage for your cryptostore - customKeyGenFunc := func(bz []byte, algo pubKeyType) (tmcrypto.PrivKey, error) { - var bzArr [32]byte - copy(bzArr[:], bz) - return secp256k1.PrivKeySecp256k1(bzArr), nil - } - cstore := NewInMemory(WithKeygenFunc(customKeyGenFunc)) - - sec := Secp256k1 - - // Add keys and see they return in alphabetical order - bob, _, err := cstore.CreateMnemonic("Bob", English, "friend", sec) - if err != nil { - // this should never happen - fmt.Println(err) - } else { - // return info here just like in List - fmt.Println(bob.GetName()) - } - _, _, _ = cstore.CreateMnemonic("Alice", English, "secret", sec) - _, _, _ = cstore.CreateMnemonic("Carl", English, "mitm", sec) - info, _ := cstore.List() - for _, i := range info { - fmt.Println(i.GetName()) - } - - // We need to use passphrase to generate a signature - tx := []byte("deadbeef") - sig, pub, err := cstore.Sign("Bob", "friend", tx) - if err != nil { - fmt.Println("don't accept real passphrase") - } - - // and we can validate the signature with publicly available info - binfo, _ := cstore.Get("Bob") - if !binfo.GetPubKey().Equals(bob.GetPubKey()) { - fmt.Println("Get and Create return different keys") - } - - if pub.Equals(binfo.GetPubKey()) { - fmt.Println("signed by Bob") - } - if !pub.VerifyBytes(tx, sig) { - fmt.Println("invalid signature") - } - - // Output: - // Bob - // Alice - // Bob - // Carl - // signed by Bob -} - -func accAddr(info Info) sdk.AccAddress { - return (sdk.AccAddress)(info.GetPubKey().Address()) -} - -var _ tmcrypto.PrivKey = testPriv{} -var _ tmcrypto.PubKey = testPub{} -var testCdc *amino.Codec - -type testPriv []byte - -func (privkey testPriv) PubKey() tmcrypto.PubKey { return testPub{} } -func (privkey testPriv) Bytes() []byte { - return testCdc.MustMarshalBinaryBare(privkey) -} -func (privkey testPriv) Sign(msg []byte) ([]byte, error) { return []byte{}, nil } -func (privkey testPriv) Equals(other tmcrypto.PrivKey) bool { return true } - -type testPub []byte - -func (key testPub) Address() tmcrypto.Address { return tmcrypto.Address{} } -func (key testPub) Bytes() []byte { - return testCdc.MustMarshalBinaryBare(key) -} -func (key testPub) VerifyBytes(msg []byte, sig []byte) bool { return true } -func (key testPub) Equals(other tmcrypto.PubKey) bool { return true } - -func TestInMemoryKeygenOverride(t *testing.T) { - // Save existing codec and reset after test - cryptoCdc := CryptoCdc - t.Cleanup(func() { - CryptoCdc = cryptoCdc - }) - - // Setup testCdc encoding and decoding new key type - testCdc = codec.New() - RegisterCodec(testCdc) - tmamino.RegisterAmino(testCdc) - - // Set up codecs for using new key types - privName, pubName := "test/priv_name", "test/pub_name" - tmamino.RegisterKeyType(testPriv{}, privName) - tmamino.RegisterKeyType(testPub{}, pubName) - testCdc.RegisterConcrete(testPriv{}, privName, nil) - testCdc.RegisterConcrete(testPub{}, pubName, nil) - CryptoCdc = testCdc - - overrideCalled := false - dummyFunc := func(bz []byte, algo pubKeyType) (tmcrypto.PrivKey, error) { - overrideCalled = true - return testPriv(bz), nil - } - - kb := NewInMemory(WithKeygenFunc(dummyFunc)) - - testName, pw := "name", "testPassword" - - // create new key which will generate with - info, _, err := kb.CreateMnemonic(testName, English, pw, Secp256k1) - require.NoError(t, err) - require.Equal(t, info.GetName(), testName) - - // Assert overridden function was called - require.True(t, overrideCalled) - - // export private key object - exported, err := kb.ExportPrivateKeyObject(testName, pw) - require.Nil(t, err, "%+v", err) - - // require that the key type is the new key - _, ok := exported.(testPriv) - require.True(t, ok) - - require.True(t, exported.PubKey().Equals(info.GetPubKey())) -} +// +// import ( +// "bytes" +// "errors" +// "fmt" +// "strings" +// "testing" +// +// "github.com/stretchr/testify/assert" +// "github.com/stretchr/testify/require" +// "github.com/tendermint/go-amino" +// tmcrypto "github.com/tendermint/tendermint/crypto" +// "github.com/tendermint/tendermint/crypto/ed25519" +// tmamino "github.com/tendermint/tendermint/crypto/encoding/amino" +// "github.com/tendermint/tendermint/crypto/multisig" +// "github.com/tendermint/tendermint/crypto/secp256k1" +// +// "github.com/cosmos/cosmos-sdk/codec" +// "github.com/cosmos/cosmos-sdk/crypto" +// "github.com/cosmos/cosmos-sdk/crypto/keys/hd" +// "github.com/cosmos/cosmos-sdk/tests" +// sdk "github.com/cosmos/cosmos-sdk/types" +// ) +// +// func init() { +// crypto.BcryptSecurityParameter = 1 +// } +// +// const ( +// nums = "1234" +// foobar = "foobar" +// ) +// +// func TestNewKeyring(t *testing.T) { +// dir, cleanup := tests.NewTestCaseDir(t) +// mockIn := strings.NewReader("") +// t.Cleanup(cleanup) +// kr, err := NewKeyring("cosmos", BackendFile, dir, mockIn) +// require.NoError(t, err) +// +// mockIn.Reset("password\npassword\n") +// info, _, err := kr.CreateMnemonic("foo", English, "password", Secp256k1) +// require.NoError(t, err) +// require.Equal(t, "foo", info.GetName()) +// } +// +// func TestKeyManagementKeyRing(t *testing.T) { +// dir, cleanup := tests.NewTestCaseDir(t) +// t.Cleanup(cleanup) +// kb, err := NewKeyring("keybasename", "test", dir, nil) +// require.NoError(t, err) +// +// algo := Secp256k1 +// n1, n2, n3 := "personal", "business", "other" +// p1, p2 := "1234", "really-secure!@#$" +// +// // Check empty state +// l, err := kb.List() +// require.Nil(t, err) +// assert.Empty(t, l) +// +// _, _, err = kb.CreateMnemonic(n1, English, p1, Ed25519) +// require.Error(t, err, "ed25519 keys are currently not supported by keybase") +// +// // create some keys +// _, err = kb.Get(n1) +// require.Error(t, err) +// i, _, err := kb.CreateMnemonic(n1, English, p1, algo) +// +// require.NoError(t, err) +// require.Equal(t, n1, i.GetName()) +// _, _, err = kb.CreateMnemonic(n2, English, p2, algo) +// require.NoError(t, err) +// +// // we can get these keys +// i2, err := kb.Get(n2) +// require.NoError(t, err) +// _, err = kb.Get(n3) +// require.NotNil(t, err) +// _, err = kb.GetByAddress(accAddr(i2)) +// require.NoError(t, err) +// addr, err := sdk.AccAddressFromBech32("cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t") +// require.NoError(t, err) +// _, err = kb.GetByAddress(addr) +// require.NotNil(t, err) +// +// // list shows them in order +// keyS, err := kb.List() +// require.NoError(t, err) +// require.Equal(t, 2, len(keyS)) +// // note these are in alphabetical order +// require.Equal(t, n2, keyS[0].GetName()) +// require.Equal(t, n1, keyS[1].GetName()) +// require.Equal(t, i2.GetPubKey(), keyS[0].GetPubKey()) +// +// // deleting a key removes it +// err = kb.Delete("bad name", "foo", false) +// require.NotNil(t, err) +// err = kb.Delete(n1, p1, false) +// require.NoError(t, err) +// keyS, err = kb.List() +// require.NoError(t, err) +// require.Equal(t, 1, len(keyS)) +// _, err = kb.Get(n1) +// require.Error(t, err) +// +// // create an offline key +// o1 := "offline" +// priv1 := ed25519.GenPrivKey() +// pub1 := priv1.PubKey() +// i, err = kb.CreateOffline(o1, pub1, Ed25519) +// require.Nil(t, err) +// require.Equal(t, pub1, i.GetPubKey()) +// require.Equal(t, o1, i.GetName()) +// keyS, err = kb.List() +// require.NoError(t, err) +// require.Equal(t, 2, len(keyS)) +// +// // delete the offline key +// err = kb.Delete(o1, "", false) +// require.NoError(t, err) +// keyS, err = kb.List() +// require.NoError(t, err) +// require.Equal(t, 1, len(keyS)) +// +// // addr cache gets nuked - and test skip flag +// require.NoError(t, kb.Delete(n2, "", true)) +// } +// +// // TestSignVerify does some detailed checks on how we sign and validate +// // signatures +// func TestSignVerifyKeyRingWithLedger(t *testing.T) { +// dir, cleanup := tests.NewTestCaseDir(t) +// t.Cleanup(cleanup) +// kb, err := NewKeyring("keybasename", "test", dir, nil) +// require.NoError(t, err) +// +// i1, err := kb.CreateLedger("key", Secp256k1, "cosmos", 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()) +// +// p1 := "1234" +// d1 := []byte("my first message") +// s1, pub1, err := kb.Sign("key", p1, d1) +// require.NoError(t, err) +// +// s2, pub2, err := SignWithLedger(i1, d1) +// require.NoError(t, err) +// +// require.Equal(t, i1.GetPubKey(), pub1) +// require.Equal(t, i1.GetPubKey(), pub2) +// require.True(t, pub1.VerifyBytes(d1, s1)) +// require.True(t, i1.GetPubKey().VerifyBytes(d1, s1)) +// require.True(t, bytes.Equal(s1, s2)) +// +// localInfo, _, err := kb.CreateMnemonic("test", English, p1, Secp256k1) +// require.NoError(t, err) +// _, _, err = SignWithLedger(localInfo, d1) +// require.Error(t, err) +// require.Equal(t, "not a ledger object", err.Error()) +// } +// +// func TestSignVerifyKeyRing(t *testing.T) { +// dir, cleanup := tests.NewTestCaseDir(t) +// t.Cleanup(cleanup) +// kb, err := NewKeyring("keybasename", "test", dir, nil) +// require.NoError(t, err) +// algo := Secp256k1 +// +// n1, n2, n3 := "some dude", "a dudette", "dude-ish" +// p1, p2, p3 := "1234", "foobar", "foobar" +// +// // create two users and get their info +// i1, _, err := kb.CreateMnemonic(n1, English, p1, algo) +// require.Nil(t, err) +// +// i2, _, err := kb.CreateMnemonic(n2, English, p2, algo) +// require.Nil(t, err) +// +// // Import a public key +// armor, err := kb.ExportPubKey(n2) +// require.Nil(t, err) +// err = kb.ImportPubKey(n3, armor) +// require.NoError(t, err) +// i3, err := kb.Get(n3) +// require.NoError(t, err) +// require.Equal(t, i3.GetName(), n3) +// +// // let's try to sign some messages +// d1 := []byte("my first message") +// d2 := []byte("some other important info!") +// d3 := []byte("feels like I forgot something...") +// +// // try signing both data with both .. +// s11, pub1, err := kb.Sign(n1, p1, d1) +// require.Nil(t, err) +// require.Equal(t, i1.GetPubKey(), pub1) +// +// s12, pub1, err := kb.Sign(n1, p1, d2) +// require.Nil(t, err) +// require.Equal(t, i1.GetPubKey(), pub1) +// +// s21, pub2, err := kb.Sign(n2, p2, d1) +// require.Nil(t, err) +// require.Equal(t, i2.GetPubKey(), pub2) +// +// s22, pub2, err := kb.Sign(n2, p2, d2) +// require.Nil(t, err) +// require.Equal(t, i2.GetPubKey(), pub2) +// +// // let's try to validate and make sure it only works when everything is proper +// cases := []struct { +// key tmcrypto.PubKey +// data []byte +// sig []byte +// valid bool +// }{ +// // proper matches +// {i1.GetPubKey(), d1, s11, true}, +// // change data, pubkey, or signature leads to fail +// {i1.GetPubKey(), d2, s11, false}, +// {i2.GetPubKey(), d1, s11, false}, +// {i1.GetPubKey(), d1, s21, false}, +// // make sure other successes +// {i1.GetPubKey(), d2, s12, true}, +// {i2.GetPubKey(), d1, s21, true}, +// {i2.GetPubKey(), d2, s22, true}, +// } +// +// for i, tc := range cases { +// valid := tc.key.VerifyBytes(tc.data, tc.sig) +// require.Equal(t, tc.valid, valid, "%d", i) +// } +// +// // Now try to sign data with a secret-less key +// _, _, err = kb.Sign(n3, p3, d3) +// require.Error(t, err) +// require.Equal(t, "cannot sign with offline keys", err.Error()) +// } +// +// func TestExportImportKeyRing(t *testing.T) { +// dir, cleanup := tests.NewTestCaseDir(t) +// t.Cleanup(cleanup) +// kb, err := NewKeyring("keybasename", "test", dir, nil) +// require.NoError(t, err) +// +// info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1) +// require.NoError(t, err) +// require.Equal(t, info.GetName(), "john") +// +// john, err := kb.Get("john") +// require.NoError(t, err) +// require.Equal(t, info.GetName(), "john") +// johnAddr := info.GetPubKey().Address() +// +// armor, err := kb.Export("john") +// require.NoError(t, err) +// +// err = kb.Import("john2", armor) +// require.NoError(t, err) +// +// john2, err := kb.Get("john2") +// require.NoError(t, err) +// +// require.Equal(t, john.GetPubKey().Address(), johnAddr) +// require.Equal(t, john.GetName(), "john") +// require.Equal(t, john, john2) +// } +// +// func TestExportImportPubKeyKeyRing(t *testing.T) { +// dir, cleanup := tests.NewTestCaseDir(t) +// t.Cleanup(cleanup) +// kb, err := NewKeyring("keybasename", "test", dir, nil) +// require.NoError(t, err) +// algo := Secp256k1 +// +// // CreateMnemonic a private-public key pair and ensure consistency +// notPasswd := "n9y25ah7" +// info, _, err := kb.CreateMnemonic("john", English, notPasswd, algo) +// require.Nil(t, err) +// require.NotEqual(t, info, "") +// require.Equal(t, info.GetName(), "john") +// addr := info.GetPubKey().Address() +// john, err := kb.Get("john") +// require.NoError(t, err) +// require.Equal(t, john.GetName(), "john") +// require.Equal(t, john.GetPubKey().Address(), addr) +// +// // Export the public key only +// armor, err := kb.ExportPubKey("john") +// require.NoError(t, err) +// // Import it under a different name +// err = kb.ImportPubKey("john-pubkey-only", armor) +// require.NoError(t, err) +// // Ensure consistency +// john2, err := kb.Get("john-pubkey-only") +// require.NoError(t, err) +// // Compare the public keys +// require.True(t, john.GetPubKey().Equals(john2.GetPubKey())) +// // Ensure the original key hasn't changed +// john, err = kb.Get("john") +// require.NoError(t, err) +// require.Equal(t, john.GetPubKey().Address(), addr) +// require.Equal(t, john.GetName(), "john") +// +// // Ensure keys cannot be overwritten +// err = kb.ImportPubKey("john-pubkey-only", armor) +// require.NotNil(t, err) +// } +// +// func TestExportPrivateKeyObjectKeyRing(t *testing.T) { +// dir, cleanup := tests.NewTestCaseDir(t) +// t.Cleanup(cleanup) +// kb, err := NewKeyring("keybasename", "test", dir, nil) +// require.NoError(t, err) +// +// info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1) +// require.NoError(t, err) +// require.Equal(t, info.GetName(), "john") +// +// // export private key object +// exported, err := kb.ExportPrivateKeyObject("john", "secretcpw") +// require.Nil(t, err, "%+v", err) +// require.True(t, exported.PubKey().Equals(info.GetPubKey())) +// } +// +// func TestAdvancedKeyManagementKeyRing(t *testing.T) { +// dir, cleanup := tests.NewTestCaseDir(t) +// t.Cleanup(cleanup) +// kb, err := NewKeyring("keybasename", "test", dir, nil) +// require.NoError(t, err) +// +// algo := Secp256k1 +// n1, n2 := "old-name", "new name" +// p1 := "1234" +// +// // make sure key works with initial password +// _, _, err = kb.CreateMnemonic(n1, English, p1, algo) +// require.Nil(t, err, "%+v", err) +// +// _, err = kb.Export(n1 + ".notreal") +// require.NotNil(t, err) +// _, err = kb.Export(" " + n1) +// require.NotNil(t, err) +// _, err = kb.Export(n1 + " ") +// require.NotNil(t, err) +// _, err = kb.Export("") +// require.NotNil(t, err) +// exported, err := kb.Export(n1) +// require.Nil(t, err, "%+v", err) +// +// // import succeeds +// err = kb.Import(n2, exported) +// require.NoError(t, err) +// +// // second import fails +// err = kb.Import(n2, exported) +// require.NotNil(t, err) +// } +// +// func TestSeedPhraseKeyRing(t *testing.T) { +// dir, cleanup := tests.NewTestCaseDir(t) +// t.Cleanup(cleanup) +// kb, err := NewKeyring("keybasename", "test", dir, nil) +// require.NoError(t, err) +// +// algo := Secp256k1 +// n1, n2 := "lost-key", "found-again" +// p1, p2 := "1234", "foobar" +// +// // make sure key works with initial password +// info, mnemonic, err := kb.CreateMnemonic(n1, English, p1, algo) +// require.Nil(t, err, "%+v", err) +// require.Equal(t, n1, info.GetName()) +// assert.NotEmpty(t, mnemonic) +// +// // now, let us delete this key +// err = kb.Delete(n1, p1, false) +// require.Nil(t, err, "%+v", err) +// _, err = kb.Get(n1) +// require.NotNil(t, err) +// +// // let us re-create it from the mnemonic-phrase +// params := *hd.NewFundraiserParams(0, sdk.CoinType, 0) +// hdPath := params.String() +// newInfo, err := kb.CreateAccount(n2, mnemonic, DefaultBIP39Passphrase, p2, hdPath, Secp256k1) +// require.NoError(t, err) +// require.Equal(t, n2, newInfo.GetName()) +// require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) +// require.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) +// } +// +// func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { +// dir, cleanup := tests.NewTestCaseDir(t) +// t.Cleanup(cleanup) +// kb, err := NewKeyring("keybasename", "test", dir, nil) +// require.NoError(t, err) +// _, _, err = kb.CreateMnemonic("john", English, "password", Secp256k1) +// require.NoError(t, err) +// +// // no error, password is irrelevant, keystr cointains ASCII armored private key +// keystr, err := kb.ExportPrivKey("john", "wrongpassword", "password") +// require.NoError(t, err) +// require.NotEmpty(t, keystr) +// +// // try import the key - wrong password +// err = kb.ImportPrivKey("john2", keystr, "somepassword") +// require.Equal(t, "failed to decrypt private key: ciphertext decryption failed", err.Error()) +// +// // try import the key with the correct password +// require.NoError(t, kb.ImportPrivKey("john2", keystr, "password")) +// +// // overwrite is not allowed +// err = kb.ImportPrivKey("john2", keystr, "password") +// require.Equal(t, "cannot overwrite key: john2", err.Error()) +// +// // try export non existing key +// _, err = kb.ExportPrivKey("john3", "wrongpassword", "password") +// require.Equal(t, "The specified item could not be found in the keyring", err.Error()) +// } +// +// func TestSupportedAlgos(t *testing.T) { +// dir, cleanup := tests.NewTestCaseDir(t) +// t.Cleanup(cleanup) +// kb, err := NewKeyring("keybasename", "test", dir, nil) +// require.NoError(t, err) +// require.Equal(t, []pubKeyType{"secp256k1"}, kb.SupportedAlgos()) +// require.Equal(t, []pubKeyType{"secp256k1"}, kb.SupportedAlgosLedger()) +// } +// +// func TestCustomDerivFuncKey(t *testing.T) { +// kb := NewInMemory(WithDeriveFunc(func(mnemonic string, bip39Passphrase, hdPath string, algo pubKeyType) ([]byte, error) { +// return nil, errors.New("cannot derive keys") +// })) +// _, _, err := kb.CreateMnemonic("test", English, "", "") +// require.Error(t, err, "cannot derive keys") +// } +// +// func TestInMemoryLanguage(t *testing.T) { +// kb := NewInMemory() +// _, _, err := kb.CreateMnemonic("something", Japanese, "no_pass", Secp256k1) +// require.Error(t, err) +// require.Equal(t, "unsupported language: only english is supported", err.Error()) +// } +// +// func TestInMemoryCreateMultisig(t *testing.T) { +// kb, err := NewKeyring("keybasename", "memory", "", nil) +// require.NoError(t, err) +// multi := multisig.PubKeyMultisigThreshold{ +// K: 1, +// PubKeys: []tmcrypto.PubKey{secp256k1.GenPrivKey().PubKey()}, +// } +// _, err = kb.CreateMulti("multi", multi) +// require.NoError(t, err) +// } +// +// func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { +// kb := NewInMemory() +// _, err := kb.CreateAccount( +// "some_account", +// "malarkey pair crucial catch public canyon evil outer stage ten gym tornado", +// "", "", CreateHDPath(0, 0).String(), Secp256k1) +// require.Error(t, err) +// require.Equal(t, "Invalid mnemonic", err.Error()) +// } +// +// func TestInMemoryCreateLedgerUnsupportedAlgo(t *testing.T) { +// kb := NewInMemory() +// +// supportedLedgerAlgos := kb.SupportedAlgosLedger() +// for _, supportedAlgo := range supportedLedgerAlgos { +// if Ed25519 == supportedAlgo { +// require.FailNow(t, "Was not an unsupported algorithm") +// } +// } +// +// _, err := kb.CreateLedger("some_account", Ed25519, "cosmos", 0, 1) +// require.Error(t, err) +// require.Equal(t, "unsupported signing algo", err.Error()) +// } +// +// func TestInMemoryCreateLedger(t *testing.T) { +// kb := NewInMemory(WithSupportedAlgosLedger([]pubKeyType{Secp256k1, Ed25519})) +// +// // test_cover and test_unit will result in different answers +// // test_cover does not compile some dependencies so ledger is disabled +// // test_unit may add a ledger mock +// // both cases are acceptable +// supportedLedgerAlgos := kb.SupportedAlgosLedger() +// secpSupported := false +// edSupported := false +// for _, supportedAlgo := range supportedLedgerAlgos { +// secpSupported = secpSupported || (supportedAlgo == Secp256k1) +// edSupported = edSupported || (supportedAlgo == Ed25519) +// } +// require.True(t, secpSupported) +// require.True(t, edSupported) +// +// ledger, err := kb.CreateLedger("some_account", Secp256k1, "cosmos", 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) +// 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() +// pk, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) +// require.NoError(t, err) +// require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) +// +// // Check that restoring the key gets the same results +// restoredKey, err := kb.Get("some_account") +// require.NoError(t, err) +// require.NotNil(t, restoredKey) +// require.Equal(t, "some_account", restoredKey.GetName()) +// require.Equal(t, TypeLedger, restoredKey.GetType()) +// pubKey = restoredKey.GetPubKey() +// pk, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) +// require.NoError(t, err) +// require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) +// +// path, err := restoredKey.GetPath() +// require.NoError(t, err) +// require.Equal(t, "44'/118'/3'/0/1", path.String()) +// } +// +// // TestInMemoryKeyManagement makes sure we can manipulate these keys well +// func TestInMemoryKeyManagement(t *testing.T) { +// // make the storage with reasonable defaults +// cstore := NewInMemory(WithSupportedAlgos([]pubKeyType{Secp256k1, Sr25519})) +// +// // Test modified supported algos +// supportedAlgos := cstore.SupportedAlgos() +// secpSupported := false +// edSupported := false +// srSupported := false +// for _, supportedAlgo := range supportedAlgos { +// secpSupported = secpSupported || (supportedAlgo == Secp256k1) +// edSupported = edSupported || (supportedAlgo == Ed25519) +// srSupported = srSupported || (supportedAlgo == Sr25519) +// } +// require.True(t, secpSupported) +// require.False(t, edSupported) +// require.True(t, srSupported) +// +// algo := Secp256k1 +// n1, n2, n3 := "personal", "business", "other" +// p1, p2 := nums, "really-secure!@#$" +// +// // Check empty state +// l, err := cstore.List() +// require.Nil(t, err) +// require.Empty(t, l) +// +// _, _, err = cstore.CreateMnemonic(n1, English, p1, Ed25519) +// require.Error(t, err, "ed25519 keys are currently not supported by keybase") +// +// // create some keys +// _, err = cstore.Get(n1) +// require.Error(t, err) +// i, _, err := cstore.CreateMnemonic(n1, English, p1, algo) +// +// require.NoError(t, err) +// require.Equal(t, n1, i.GetName()) +// _, _, err = cstore.CreateMnemonic(n2, English, p2, algo) +// require.NoError(t, err) +// +// // we can get these keys +// i2, err := cstore.Get(n2) +// require.NoError(t, err) +// _, err = cstore.Get(n3) +// require.NotNil(t, err) +// _, err = cstore.GetByAddress(accAddr(i2)) +// require.NoError(t, err) +// addr, err := sdk.AccAddressFromBech32("cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t") +// require.NoError(t, err) +// _, err = cstore.GetByAddress(addr) +// require.NotNil(t, err) +// +// // list shows them in order +// keyS, err := cstore.List() +// require.NoError(t, err) +// require.Equal(t, 2, len(keyS)) +// // note these are in alphabetical order +// require.Equal(t, n2, keyS[0].GetName()) +// require.Equal(t, n1, keyS[1].GetName()) +// require.Equal(t, i2.GetPubKey(), keyS[0].GetPubKey()) +// +// // deleting a key removes it +// err = cstore.Delete("bad name", "foo", false) +// require.NotNil(t, err) +// err = cstore.Delete(n1, p1, false) +// require.NoError(t, err) +// keyS, err = cstore.List() +// require.NoError(t, err) +// require.Equal(t, 1, len(keyS)) +// _, err = cstore.Get(n1) +// require.Error(t, err) +// +// // create an offline key +// o1 := "offline" +// priv1 := ed25519.GenPrivKey() +// pub1 := priv1.PubKey() +// i, err = cstore.CreateOffline(o1, pub1, algo) +// require.Nil(t, err) +// require.Equal(t, pub1, i.GetPubKey()) +// require.Equal(t, o1, i.GetName()) +// iOffline := i.(*offlineInfo) +// require.Equal(t, algo, iOffline.GetAlgo()) +// keyS, err = cstore.List() +// require.NoError(t, err) +// require.Equal(t, 2, len(keyS)) +// +// // delete the offline key +// err = cstore.Delete(o1, "", false) +// require.NoError(t, err) +// keyS, err = cstore.List() +// require.NoError(t, err) +// require.Equal(t, 1, len(keyS)) +// +// // addr cache gets nuked - and test skip flag +// err = cstore.Delete(n2, "", true) +// require.NoError(t, err) +// } +// +// // TestInMemorySignVerify does some detailed checks on how we sign and validate +// // signatures +// func TestInMemorySignVerify(t *testing.T) { +// cstore := NewInMemory() +// algo := Secp256k1 +// +// n1, n2, n3 := "some dude", "a dudette", "dude-ish" +// p1, p2, p3 := nums, foobar, foobar +// +// // create two users and get their info +// i1, _, err := cstore.CreateMnemonic(n1, English, p1, algo) +// require.Nil(t, err) +// +// i2, _, err := cstore.CreateMnemonic(n2, English, p2, algo) +// require.Nil(t, err) +// +// // Import a public key +// armor, err := cstore.ExportPubKey(n2) +// require.Nil(t, err) +// err = cstore.ImportPubKey(n3, armor) +// require.NoError(t, err) +// i3, err := cstore.Get(n3) +// require.NoError(t, err) +// require.Equal(t, i3.GetName(), n3) +// +// // let's try to sign some messages +// d1 := []byte("my first message") +// d2 := []byte("some other important info!") +// d3 := []byte("feels like I forgot something...") +// +// // try signing both data with both .. +// s11, pub1, err := cstore.Sign(n1, p1, d1) +// require.Nil(t, err) +// require.Equal(t, i1.GetPubKey(), pub1) +// +// s12, pub1, err := cstore.Sign(n1, p1, d2) +// require.Nil(t, err) +// require.Equal(t, i1.GetPubKey(), pub1) +// +// s21, pub2, err := cstore.Sign(n2, p2, d1) +// require.Nil(t, err) +// require.Equal(t, i2.GetPubKey(), pub2) +// +// s22, pub2, err := cstore.Sign(n2, p2, d2) +// require.Nil(t, err) +// require.Equal(t, i2.GetPubKey(), pub2) +// +// // let's try to validate and make sure it only works when everything is proper +// cases := []struct { +// key tmcrypto.PubKey +// data []byte +// sig []byte +// valid bool +// }{ +// // proper matches +// {i1.GetPubKey(), d1, s11, true}, +// // change data, pubkey, or signature leads to fail +// {i1.GetPubKey(), d2, s11, false}, +// {i2.GetPubKey(), d1, s11, false}, +// {i1.GetPubKey(), d1, s21, false}, +// // make sure other successes +// {i1.GetPubKey(), d2, s12, true}, +// {i2.GetPubKey(), d1, s21, true}, +// {i2.GetPubKey(), d2, s22, true}, +// } +// +// for i, tc := range cases { +// valid := tc.key.VerifyBytes(tc.data, tc.sig) +// require.Equal(t, tc.valid, valid, "%d", i) +// } +// +// // Now try to sign data with a secret-less key +// _, _, err = cstore.Sign(n3, p3, d3) +// require.Error(t, err) +// require.Equal(t, "cannot sign with offline keys", err.Error()) +// } +// +// // TestInMemoryExportImport tests exporting and importing +// func TestInMemoryExportImport(t *testing.T) { +// // make the storage with reasonable defaults +// cstore := NewInMemory() +// +// info, _, err := cstore.CreateMnemonic("john", English, "secretcpw", Secp256k1) +// require.NoError(t, err) +// require.Equal(t, info.GetName(), "john") +// +// john, err := cstore.Get("john") +// require.NoError(t, err) +// require.Equal(t, info.GetName(), "john") +// johnAddr := info.GetPubKey().Address() +// +// armor, err := cstore.Export("john") +// require.NoError(t, err) +// +// err = cstore.Import("john2", armor) +// require.NoError(t, err) +// +// john2, err := cstore.Get("john2") +// require.NoError(t, err) +// +// require.Equal(t, john.GetPubKey().Address(), johnAddr) +// require.Equal(t, john.GetName(), "john") +// require.Equal(t, john, john2) +// } +// +// func TestInMemoryExportImportPrivKey(t *testing.T) { +// kb := NewInMemory() +// +// info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1) +// require.NoError(t, err) +// require.Equal(t, info.GetName(), "john") +// priv1, err := kb.Get("john") +// require.NoError(t, err) +// +// // decrypt local private key, and produce encrypted ASCII armored output +// armored, err := kb.ExportPrivKey("john", "secretcpw", "new_secretcpw") +// require.NoError(t, err) +// +// // delete exported key +// require.NoError(t, kb.Delete("john", "", true)) +// _, err = kb.Get("john") +// require.Error(t, err) +// +// // import armored key +// require.NoError(t, kb.ImportPrivKey("john", armored, "new_secretcpw")) +// +// // ensure old and new keys match +// priv2, err := kb.Get("john") +// require.NoError(t, err) +// require.True(t, priv1.GetPubKey().Equals(priv2.GetPubKey())) +// } +// +// func TestInMemoryExportImportPubKey(t *testing.T) { +// // make the storage with reasonable defaults +// cstore := NewInMemory() +// +// // CreateMnemonic a private-public key pair and ensure consistency +// notPasswd := "n9y25ah7" +// info, _, err := cstore.CreateMnemonic("john", English, notPasswd, Secp256k1) +// require.Nil(t, err) +// require.NotEqual(t, info, "") +// require.Equal(t, info.GetName(), "john") +// addr := info.GetPubKey().Address() +// john, err := cstore.Get("john") +// require.NoError(t, err) +// require.Equal(t, john.GetName(), "john") +// require.Equal(t, john.GetPubKey().Address(), addr) +// +// // Export the public key only +// armor, err := cstore.ExportPubKey("john") +// require.NoError(t, err) +// // Import it under a different name +// err = cstore.ImportPubKey("john-pubkey-only", armor) +// require.NoError(t, err) +// // Ensure consistency +// john2, err := cstore.Get("john-pubkey-only") +// require.NoError(t, err) +// // Compare the public keys +// require.True(t, john.GetPubKey().Equals(john2.GetPubKey())) +// // Ensure the original key hasn't changed +// john, err = cstore.Get("john") +// require.NoError(t, err) +// require.Equal(t, john.GetPubKey().Address(), addr) +// require.Equal(t, john.GetName(), "john") +// +// // Ensure keys cannot be overwritten +// err = cstore.ImportPubKey("john-pubkey-only", armor) +// require.NotNil(t, err) +// } +// +// func TestInMemoryExportPrivateKeyObject(t *testing.T) { +// kb := NewInMemory() +// +// info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1) +// require.NoError(t, err) +// require.Equal(t, info.GetName(), "john") +// +// // export private key object +// _, err = kb.ExportPrivateKeyObject("john", "invalid") +// require.NoError(t, err, "%+v", err) +// exported, err := kb.ExportPrivateKeyObject("john", "secretcpw") +// require.Nil(t, err, "%+v", err) +// require.True(t, exported.PubKey().Equals(info.GetPubKey())) +// } +// +// // TestInMemoryAdvancedKeyManagement verifies update, import, export functionality +// func TestInMemoryAdvancedKeyManagement(t *testing.T) { +// // make the storage with reasonable defaults +// cstore := NewInMemory() +// +// algo := Secp256k1 +// n1, n2 := "old-name", "new name" +// p1 := nums +// +// // make sure key works with initial password +// _, _, err := cstore.CreateMnemonic(n1, English, p1, algo) +// require.Nil(t, err, "%+v", err) +// +// // exporting requires the proper name and passphrase +// _, err = cstore.Export(n1 + ".notreal") +// require.NotNil(t, err) +// _, err = cstore.Export(" " + n1) +// require.NotNil(t, err) +// _, err = cstore.Export(n1 + " ") +// require.NotNil(t, err) +// _, err = cstore.Export("") +// require.NotNil(t, err) +// exported, err := cstore.Export(n1) +// require.Nil(t, err, "%+v", err) +// +// // import succeeds +// err = cstore.Import(n2, exported) +// require.NoError(t, err) +// +// // second import fails +// err = cstore.Import(n2, exported) +// require.NotNil(t, err) +// } +// +// // TestInMemorySeedPhrase verifies restoring from a seed phrase +// func TestInMemorySeedPhrase(t *testing.T) { +// +// // make the storage with reasonable defaults +// cstore := NewInMemory() +// +// algo := Secp256k1 +// n1, n2 := "lost-key", "found-again" +// p1, p2 := nums, foobar +// +// // make sure key works with initial password +// info, mnemonic, err := cstore.CreateMnemonic(n1, English, p1, algo) +// require.Nil(t, err, "%+v", err) +// require.Equal(t, n1, info.GetName()) +// require.NotEmpty(t, mnemonic) +// +// // now, let us delete this key +// err = cstore.Delete(n1, p1, false) +// require.Nil(t, err, "%+v", err) +// _, err = cstore.Get(n1) +// require.NotNil(t, err) +// +// // let us re-create it from the mnemonic-phrase +// params := *hd.NewFundraiserParams(0, sdk.CoinType, 0) +// hdPath := params.String() +// newInfo, err := cstore.CreateAccount(n2, mnemonic, DefaultBIP39Passphrase, p2, hdPath, Secp256k1) +// require.NoError(t, err) +// require.Equal(t, n2, newInfo.GetName()) +// require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) +// require.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) +// } +// +// func ExampleNew() { +// // Select the encryption and storage for your cryptostore +// customKeyGenFunc := func(bz []byte, algo pubKeyType) (tmcrypto.PrivKey, error) { +// var bzArr [32]byte +// copy(bzArr[:], bz) +// return secp256k1.PrivKeySecp256k1(bzArr), nil +// } +// cstore := NewInMemory(WithKeygenFunc(customKeyGenFunc)) +// +// sec := Secp256k1 +// +// // Add keys and see they return in alphabetical order +// bob, _, err := cstore.CreateMnemonic("Bob", English, "friend", sec) +// if err != nil { +// // this should never happen +// fmt.Println(err) +// } else { +// // return info here just like in List +// fmt.Println(bob.GetName()) +// } +// _, _, _ = cstore.CreateMnemonic("Alice", English, "secret", sec) +// _, _, _ = cstore.CreateMnemonic("Carl", English, "mitm", sec) +// info, _ := cstore.List() +// for _, i := range info { +// fmt.Println(i.GetName()) +// } +// +// // We need to use passphrase to generate a signature +// tx := []byte("deadbeef") +// sig, pub, err := cstore.Sign("Bob", "friend", tx) +// if err != nil { +// fmt.Println("don't accept real passphrase") +// } +// +// // and we can validate the signature with publicly available info +// binfo, _ := cstore.Get("Bob") +// if !binfo.GetPubKey().Equals(bob.GetPubKey()) { +// fmt.Println("Get and Create return different keys") +// } +// +// if pub.Equals(binfo.GetPubKey()) { +// fmt.Println("signed by Bob") +// } +// if !pub.VerifyBytes(tx, sig) { +// fmt.Println("invalid signature") +// } +// +// // Output: +// // Bob +// // Alice +// // Bob +// // Carl +// // signed by Bob +// } +// +// func accAddr(info Info) sdk.AccAddress { +// return (sdk.AccAddress)(info.GetPubKey().Address()) +// } +// +// var _ tmcrypto.PrivKey = testPriv{} +// var _ tmcrypto.PubKey = testPub{} +// var testCdc *amino.Codec +// +// type testPriv []byte +// +// func (privkey testPriv) PubKey() tmcrypto.PubKey { return testPub{} } +// func (privkey testPriv) Bytes() []byte { +// return testCdc.MustMarshalBinaryBare(privkey) +// } +// func (privkey testPriv) Sign(msg []byte) ([]byte, error) { return []byte{}, nil } +// func (privkey testPriv) Equals(other tmcrypto.PrivKey) bool { return true } +// +// type testPub []byte +// +// func (key testPub) Address() tmcrypto.Address { return tmcrypto.Address{} } +// func (key testPub) Bytes() []byte { +// return testCdc.MustMarshalBinaryBare(key) +// } +// func (key testPub) VerifyBytes(msg []byte, sig []byte) bool { return true } +// func (key testPub) Equals(other tmcrypto.PubKey) bool { return true } +// +// func TestInMemoryKeygenOverride(t *testing.T) { +// // Save existing codec and reset after test +// cryptoCdc := CryptoCdc +// t.Cleanup(func() { +// CryptoCdc = cryptoCdc +// }) +// +// // Setup testCdc encoding and decoding new key type +// testCdc = codec.New() +// RegisterCodec(testCdc) +// tmamino.RegisterAmino(testCdc) +// +// // Set up codecs for using new key types +// privName, pubName := "test/priv_name", "test/pub_name" +// tmamino.RegisterKeyType(testPriv{}, privName) +// tmamino.RegisterKeyType(testPub{}, pubName) +// testCdc.RegisterConcrete(testPriv{}, privName, nil) +// testCdc.RegisterConcrete(testPub{}, pubName, nil) +// CryptoCdc = testCdc +// +// overrideCalled := false +// dummyFunc := func(bz []byte, algo pubKeyType) (tmcrypto.PrivKey, error) { +// overrideCalled = true +// return testPriv(bz), nil +// } +// +// kb := NewInMemory(WithKeygenFunc(dummyFunc)) +// +// testName, pw := "name", "testPassword" +// +// // create new key which will generate with +// info, _, err := kb.CreateMnemonic(testName, English, pw, Secp256k1) +// require.NoError(t, err) +// require.Equal(t, info.GetName(), testName) +// +// // Assert overridden function was called +// require.True(t, overrideCalled) +// +// // export private key object +// exported, err := kb.ExportPrivateKeyObject(testName, pw) +// require.Nil(t, err, "%+v", err) +// +// // require that the key type is the new key +// _, ok := exported.(testPriv) +// require.True(t, ok) +// +// require.True(t, exported.PubKey().Equals(info.GetPubKey())) +// } From 519939e370437b7e646189959792501ba6f8c4a2 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 18:56:32 +0200 Subject: [PATCH 085/148] fix armor test --- crypto/armor_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/armor_test.go b/crypto/armor_test.go index 29aeb6af64a..621a8bf38eb 100644 --- a/crypto/armor_test.go +++ b/crypto/armor_test.go @@ -70,7 +70,7 @@ func TestArmorUnarmorPubKey(t *testing.T) { cstore := keyring.NewInMemory() // Add keys and see they return in alphabetical order - info, _, err := cstore.CreateMnemonic("Bob", keyring.English, "passphrase", keyring.Secp256k1) + info, _, err := cstore.NewMnemonic("Bob", keyring.English, keyring.AltSecp256k1) require.NoError(t, err) armored := crypto.ArmorPubKeyBytes(info.GetPubKey().Bytes(), "") pubBytes, algo, err := crypto.UnarmorPubKeyBytes(armored) @@ -88,7 +88,7 @@ func TestArmorUnarmorPubKey(t *testing.T) { require.Equal(t, "unknown", algo) require.True(t, pub.Equals(info.GetPubKey())) - armored, err = cstore.ExportPrivKey("Bob", "passphrase", "alessio") + armored, err = cstore.ExportPrivKeyArmor("Bob", "passphrase") require.NoError(t, err) _, _, err = crypto.UnarmorPubKeyBytes(armored) require.Error(t, err) From 92acbff8163dc515e7aef9e3a4f753f17fae2dbc Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 19:22:20 +0200 Subject: [PATCH 086/148] migrate some tests --- crypto/keyring/altkeyring.go | 4 +- crypto/keyring/altkeyring_test.go | 2 +- crypto/keyring/keyring.go | 2 +- crypto/keyring/keyring_test.go | 254 ++++++++++++++---------------- 4 files changed, 125 insertions(+), 137 deletions(-) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index f244763852b..198cae7df49 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -278,8 +278,8 @@ func (ks keystore) SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error return ks.writeMultisigKey(uid, pubkey) } -func (ks keystore) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo AltSigningAlgo) (Info, error) { - return ks.writeOfflineKey(uid, pubkey, algo.Name()) +func (ks keystore) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo pubKeyType) (Info, error) { + return ks.writeOfflineKey(uid, pubkey, algo) } func (ks keystore) DeleteByAddress(address types.Address) error { diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 500785bcc2b..015cb42f844 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -217,7 +217,7 @@ func TestAltKeyring_SavePubKey(t *testing.T) { priv := ed25519.GenPrivKey() pub := priv.PubKey() - info, err := keyring.SavePubKey(key, pub, AltSecp256k1) + info, err := keyring.SavePubKey(key, pub, AltSecp256k1.Name()) require.Nil(t, err) require.Equal(t, pub, info.GetPubKey()) require.Equal(t, key, info.GetName()) diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index f4a5988df0f..51851955596 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -67,7 +67,7 @@ type Keyring interface { SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, account, index uint32) (Info, error) // SavePubKey stores a public key and returns the persisted Info structure. - SavePubKey(uid string, pubkey tmcrypto.PubKey, algo AltSigningAlgo) (Info, error) + SavePubKey(uid string, pubkey tmcrypto.PubKey, algo pubKeyType) (Info, error) // SaveMultisig stores and returns a new multsig (offline) key reference. SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 076172de84a..0f6edd1cdf1 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -1,134 +1,122 @@ package keyring -// -// import ( -// "bytes" -// "errors" -// "fmt" -// "strings" -// "testing" -// -// "github.com/stretchr/testify/assert" -// "github.com/stretchr/testify/require" -// "github.com/tendermint/go-amino" -// tmcrypto "github.com/tendermint/tendermint/crypto" -// "github.com/tendermint/tendermint/crypto/ed25519" -// tmamino "github.com/tendermint/tendermint/crypto/encoding/amino" -// "github.com/tendermint/tendermint/crypto/multisig" -// "github.com/tendermint/tendermint/crypto/secp256k1" -// -// "github.com/cosmos/cosmos-sdk/codec" -// "github.com/cosmos/cosmos-sdk/crypto" -// "github.com/cosmos/cosmos-sdk/crypto/keys/hd" -// "github.com/cosmos/cosmos-sdk/tests" -// sdk "github.com/cosmos/cosmos-sdk/types" -// ) -// -// func init() { -// crypto.BcryptSecurityParameter = 1 -// } -// -// const ( -// nums = "1234" -// foobar = "foobar" -// ) -// -// func TestNewKeyring(t *testing.T) { -// dir, cleanup := tests.NewTestCaseDir(t) -// mockIn := strings.NewReader("") -// t.Cleanup(cleanup) -// kr, err := NewKeyring("cosmos", BackendFile, dir, mockIn) -// require.NoError(t, err) -// -// mockIn.Reset("password\npassword\n") -// info, _, err := kr.CreateMnemonic("foo", English, "password", Secp256k1) -// require.NoError(t, err) -// require.Equal(t, "foo", info.GetName()) -// } -// -// func TestKeyManagementKeyRing(t *testing.T) { -// dir, cleanup := tests.NewTestCaseDir(t) -// t.Cleanup(cleanup) -// kb, err := NewKeyring("keybasename", "test", dir, nil) -// require.NoError(t, err) -// -// algo := Secp256k1 -// n1, n2, n3 := "personal", "business", "other" -// p1, p2 := "1234", "really-secure!@#$" -// -// // Check empty state -// l, err := kb.List() -// require.Nil(t, err) -// assert.Empty(t, l) -// -// _, _, err = kb.CreateMnemonic(n1, English, p1, Ed25519) -// require.Error(t, err, "ed25519 keys are currently not supported by keybase") -// -// // create some keys -// _, err = kb.Get(n1) -// require.Error(t, err) -// i, _, err := kb.CreateMnemonic(n1, English, p1, algo) -// -// require.NoError(t, err) -// require.Equal(t, n1, i.GetName()) -// _, _, err = kb.CreateMnemonic(n2, English, p2, algo) -// require.NoError(t, err) -// -// // we can get these keys -// i2, err := kb.Get(n2) -// require.NoError(t, err) -// _, err = kb.Get(n3) -// require.NotNil(t, err) -// _, err = kb.GetByAddress(accAddr(i2)) -// require.NoError(t, err) -// addr, err := sdk.AccAddressFromBech32("cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t") -// require.NoError(t, err) -// _, err = kb.GetByAddress(addr) -// require.NotNil(t, err) -// -// // list shows them in order -// keyS, err := kb.List() -// require.NoError(t, err) -// require.Equal(t, 2, len(keyS)) -// // note these are in alphabetical order -// require.Equal(t, n2, keyS[0].GetName()) -// require.Equal(t, n1, keyS[1].GetName()) -// require.Equal(t, i2.GetPubKey(), keyS[0].GetPubKey()) -// -// // deleting a key removes it -// err = kb.Delete("bad name", "foo", false) -// require.NotNil(t, err) -// err = kb.Delete(n1, p1, false) -// require.NoError(t, err) -// keyS, err = kb.List() -// require.NoError(t, err) -// require.Equal(t, 1, len(keyS)) -// _, err = kb.Get(n1) -// require.Error(t, err) -// -// // create an offline key -// o1 := "offline" -// priv1 := ed25519.GenPrivKey() -// pub1 := priv1.PubKey() -// i, err = kb.CreateOffline(o1, pub1, Ed25519) -// require.Nil(t, err) -// require.Equal(t, pub1, i.GetPubKey()) -// require.Equal(t, o1, i.GetName()) -// keyS, err = kb.List() -// require.NoError(t, err) -// require.Equal(t, 2, len(keyS)) -// -// // delete the offline key -// err = kb.Delete(o1, "", false) -// require.NoError(t, err) -// keyS, err = kb.List() -// require.NoError(t, err) -// require.Equal(t, 1, len(keyS)) -// -// // addr cache gets nuked - and test skip flag -// require.NoError(t, kb.Delete(n2, "", true)) -// } -// +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/crypto/ed25519" + + "github.com/cosmos/cosmos-sdk/crypto" + "github.com/cosmos/cosmos-sdk/tests" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func init() { + crypto.BcryptSecurityParameter = 1 +} + +const ( + nums = "1234" + foobar = "foobar" +) + +func TestNewKeyring(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + mockIn := strings.NewReader("") + t.Cleanup(cleanup) + kr, err := New("cosmos", BackendFile, dir, mockIn) + require.NoError(t, err) + + mockIn.Reset("password\npassword\n") + info, _, err := kr.NewMnemonic("foo", English, AltSecp256k1) + require.NoError(t, err) + require.Equal(t, "foo", info.GetName()) +} + +func TestKeyManagementKeyRing(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + t.Cleanup(cleanup) + kb, err := New("keybasename", "test", dir, nil) + require.NoError(t, err) + + algo := AltSecp256k1 + n1, n2, n3 := "personal", "business", "other" + + // Check empty state + l, err := kb.List() + require.Nil(t, err) + assert.Empty(t, l) + + _, _, err = kb.NewMnemonic(n1, English, notSupportedAlgo{}) + require.Error(t, err, "ed25519 keys are currently not supported by keybase") + + // create some keys + _, err = kb.Key(n1) + require.Error(t, err) + i, _, err := kb.NewMnemonic(n1, English, algo) + + require.NoError(t, err) + require.Equal(t, n1, i.GetName()) + _, _, err = kb.NewMnemonic(n2, English, algo) + require.NoError(t, err) + + // we can get these keys + i2, err := kb.Key(n2) + require.NoError(t, err) + _, err = kb.Key(n3) + require.NotNil(t, err) + _, err = kb.KeyByAddress(accAddr(i2)) + require.NoError(t, err) + addr, err := sdk.AccAddressFromBech32("cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t") + require.NoError(t, err) + _, err = kb.KeyByAddress(addr) + require.NotNil(t, err) + + // list shows them in order + keyS, err := kb.List() + require.NoError(t, err) + require.Equal(t, 2, len(keyS)) + // note these are in alphabetical order + require.Equal(t, n2, keyS[0].GetName()) + require.Equal(t, n1, keyS[1].GetName()) + require.Equal(t, i2.GetPubKey(), keyS[0].GetPubKey()) + + // deleting a key removes it + err = kb.Delete("bad name") + require.NotNil(t, err) + err = kb.Delete(n1) + require.NoError(t, err) + keyS, err = kb.List() + require.NoError(t, err) + require.Equal(t, 1, len(keyS)) + _, err = kb.Key(n1) + require.Error(t, err) + + // create an offline key + o1 := "offline" + priv1 := ed25519.GenPrivKey() + pub1 := priv1.PubKey() + i, err = kb.SavePubKey(o1, pub1, Ed25519) + require.Nil(t, err) + require.Equal(t, pub1, i.GetPubKey()) + require.Equal(t, o1, i.GetName()) + keyS, err = kb.List() + require.NoError(t, err) + require.Equal(t, 2, len(keyS)) + + // delete the offline key + err = kb.Delete(o1) + require.NoError(t, err) + keyS, err = kb.List() + require.NoError(t, err) + require.Equal(t, 1, len(keyS)) + + // addr cache gets nuked - and test skip flag + require.NoError(t, kb.Delete(n2)) +} + // // TestSignVerify does some detailed checks on how we sign and validate // // signatures // func TestSignVerifyKeyRingWithLedger(t *testing.T) { @@ -939,10 +927,10 @@ package keyring // // signed by Bob // } // -// func accAddr(info Info) sdk.AccAddress { -// return (sdk.AccAddress)(info.GetPubKey().Address()) -// } -// +func accAddr(info Info) sdk.AccAddress { + return (sdk.AccAddress)(info.GetPubKey().Address()) +} + // var _ tmcrypto.PrivKey = testPriv{} // var _ tmcrypto.PubKey = testPub{} // var testCdc *amino.Codec From d03a7e32171cb43b9fb6f88c0bf82ee6263ba145 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 19:24:23 +0200 Subject: [PATCH 087/148] migrate more tests --- crypto/keyring/keyring_test.go | 74 +++++++++++++++++----------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 0f6edd1cdf1..a33e9c2b5ba 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -1,6 +1,7 @@ package keyring import ( + "bytes" "strings" "testing" @@ -117,43 +118,42 @@ func TestKeyManagementKeyRing(t *testing.T) { require.NoError(t, kb.Delete(n2)) } -// // TestSignVerify does some detailed checks on how we sign and validate -// // signatures -// func TestSignVerifyKeyRingWithLedger(t *testing.T) { -// dir, cleanup := tests.NewTestCaseDir(t) -// t.Cleanup(cleanup) -// kb, err := NewKeyring("keybasename", "test", dir, nil) -// require.NoError(t, err) -// -// i1, err := kb.CreateLedger("key", Secp256k1, "cosmos", 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()) -// -// p1 := "1234" -// d1 := []byte("my first message") -// s1, pub1, err := kb.Sign("key", p1, d1) -// require.NoError(t, err) -// -// s2, pub2, err := SignWithLedger(i1, d1) -// require.NoError(t, err) -// -// require.Equal(t, i1.GetPubKey(), pub1) -// require.Equal(t, i1.GetPubKey(), pub2) -// require.True(t, pub1.VerifyBytes(d1, s1)) -// require.True(t, i1.GetPubKey().VerifyBytes(d1, s1)) -// require.True(t, bytes.Equal(s1, s2)) -// -// localInfo, _, err := kb.CreateMnemonic("test", English, p1, Secp256k1) -// require.NoError(t, err) -// _, _, err = SignWithLedger(localInfo, d1) -// require.Error(t, err) -// require.Equal(t, "not a ledger object", err.Error()) -// } -// +// TestSignVerify does some detailed checks on how we sign and validate +// signatures +func TestSignVerifyKeyRingWithLedger(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + t.Cleanup(cleanup) + kb, err := New("keybasename", "test", dir, nil) + require.NoError(t, err) + + i1, err := kb.SaveLedgerKey("key", AltSecp256k1, "cosmos", 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()) + + d1 := []byte("my first message") + s1, pub1, err := kb.Sign("key", d1) + require.NoError(t, err) + + s2, pub2, err := SignWithLedger(i1, d1) + require.NoError(t, err) + + require.Equal(t, i1.GetPubKey(), pub1) + require.Equal(t, i1.GetPubKey(), pub2) + require.True(t, pub1.VerifyBytes(d1, s1)) + require.True(t, i1.GetPubKey().VerifyBytes(d1, s1)) + require.True(t, bytes.Equal(s1, s2)) + + localInfo, _, err := kb.NewMnemonic("test", English, AltSecp256k1) + require.NoError(t, err) + _, _, err = SignWithLedger(localInfo, d1) + require.Error(t, err) + require.Equal(t, "not a ledger object", err.Error()) +} + // func TestSignVerifyKeyRing(t *testing.T) { // dir, cleanup := tests.NewTestCaseDir(t) // t.Cleanup(cleanup) From 93d16c98036762e32438a893f014816c6a03a64a Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 19:26:29 +0200 Subject: [PATCH 088/148] migrate TestSignVerifyKeyRing --- crypto/keyring/keyring_test.go | 157 +++++++++++++++++---------------- 1 file changed, 80 insertions(+), 77 deletions(-) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index a33e9c2b5ba..6c573822961 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -5,6 +5,8 @@ import ( "strings" "testing" + tmcrypto "github.com/tendermint/tendermint/crypto" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto/ed25519" @@ -154,83 +156,84 @@ func TestSignVerifyKeyRingWithLedger(t *testing.T) { require.Equal(t, "not a ledger object", err.Error()) } -// func TestSignVerifyKeyRing(t *testing.T) { -// dir, cleanup := tests.NewTestCaseDir(t) -// t.Cleanup(cleanup) -// kb, err := NewKeyring("keybasename", "test", dir, nil) -// require.NoError(t, err) -// algo := Secp256k1 -// -// n1, n2, n3 := "some dude", "a dudette", "dude-ish" -// p1, p2, p3 := "1234", "foobar", "foobar" -// -// // create two users and get their info -// i1, _, err := kb.CreateMnemonic(n1, English, p1, algo) -// require.Nil(t, err) -// -// i2, _, err := kb.CreateMnemonic(n2, English, p2, algo) -// require.Nil(t, err) -// -// // Import a public key -// armor, err := kb.ExportPubKey(n2) -// require.Nil(t, err) -// err = kb.ImportPubKey(n3, armor) -// require.NoError(t, err) -// i3, err := kb.Get(n3) -// require.NoError(t, err) -// require.Equal(t, i3.GetName(), n3) -// -// // let's try to sign some messages -// d1 := []byte("my first message") -// d2 := []byte("some other important info!") -// d3 := []byte("feels like I forgot something...") -// -// // try signing both data with both .. -// s11, pub1, err := kb.Sign(n1, p1, d1) -// require.Nil(t, err) -// require.Equal(t, i1.GetPubKey(), pub1) -// -// s12, pub1, err := kb.Sign(n1, p1, d2) -// require.Nil(t, err) -// require.Equal(t, i1.GetPubKey(), pub1) -// -// s21, pub2, err := kb.Sign(n2, p2, d1) -// require.Nil(t, err) -// require.Equal(t, i2.GetPubKey(), pub2) -// -// s22, pub2, err := kb.Sign(n2, p2, d2) -// require.Nil(t, err) -// require.Equal(t, i2.GetPubKey(), pub2) -// -// // let's try to validate and make sure it only works when everything is proper -// cases := []struct { -// key tmcrypto.PubKey -// data []byte -// sig []byte -// valid bool -// }{ -// // proper matches -// {i1.GetPubKey(), d1, s11, true}, -// // change data, pubkey, or signature leads to fail -// {i1.GetPubKey(), d2, s11, false}, -// {i2.GetPubKey(), d1, s11, false}, -// {i1.GetPubKey(), d1, s21, false}, -// // make sure other successes -// {i1.GetPubKey(), d2, s12, true}, -// {i2.GetPubKey(), d1, s21, true}, -// {i2.GetPubKey(), d2, s22, true}, -// } -// -// for i, tc := range cases { -// valid := tc.key.VerifyBytes(tc.data, tc.sig) -// require.Equal(t, tc.valid, valid, "%d", i) -// } -// -// // Now try to sign data with a secret-less key -// _, _, err = kb.Sign(n3, p3, d3) -// require.Error(t, err) -// require.Equal(t, "cannot sign with offline keys", err.Error()) -// } +func TestSignVerifyKeyRing(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + t.Cleanup(cleanup) + + kb, err := New("keybasename", "test", dir, nil) + require.NoError(t, err) + algo := AltSecp256k1 + + n1, n2, n3 := "some dude", "a dudette", "dude-ish" + + // create two users and get their info + i1, _, err := kb.NewMnemonic(n1, English, algo) + require.Nil(t, err) + + i2, _, err := kb.NewMnemonic(n2, English, algo) + require.Nil(t, err) + + // Import a public key + armor, err := kb.ExportPubKeyArmor(n2) + require.Nil(t, err) + err = kb.ImportPubKey(n3, armor) + require.NoError(t, err) + i3, err := kb.Key(n3) + require.NoError(t, err) + require.Equal(t, i3.GetName(), n3) + + // let's try to sign some messages + d1 := []byte("my first message") + d2 := []byte("some other important info!") + d3 := []byte("feels like I forgot something...") + + // try signing both data with both .. + s11, pub1, err := kb.Sign(n1, d1) + require.Nil(t, err) + require.Equal(t, i1.GetPubKey(), pub1) + + s12, pub1, err := kb.Sign(n1, d2) + require.Nil(t, err) + require.Equal(t, i1.GetPubKey(), pub1) + + s21, pub2, err := kb.Sign(n2, d1) + require.Nil(t, err) + require.Equal(t, i2.GetPubKey(), pub2) + + s22, pub2, err := kb.Sign(n2, d2) + require.Nil(t, err) + require.Equal(t, i2.GetPubKey(), pub2) + + // let's try to validate and make sure it only works when everything is proper + cases := []struct { + key tmcrypto.PubKey + data []byte + sig []byte + valid bool + }{ + // proper matches + {i1.GetPubKey(), d1, s11, true}, + // change data, pubkey, or signature leads to fail + {i1.GetPubKey(), d2, s11, false}, + {i2.GetPubKey(), d1, s11, false}, + {i1.GetPubKey(), d1, s21, false}, + // make sure other successes + {i1.GetPubKey(), d2, s12, true}, + {i2.GetPubKey(), d1, s21, true}, + {i2.GetPubKey(), d2, s22, true}, + } + + for i, tc := range cases { + valid := tc.key.VerifyBytes(tc.data, tc.sig) + require.Equal(t, tc.valid, valid, "%d", i) + } + + // Now try to sign data with a secret-less key + _, _, err = kb.Sign(n3, d3) + require.Error(t, err) + require.Equal(t, "cannot sign with offline keys", err.Error()) +} + // // func TestExportImportKeyRing(t *testing.T) { // dir, cleanup := tests.NewTestCaseDir(t) From fc3596c4308e2631789e42ac5d936d99527a192d Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 19:34:22 +0200 Subject: [PATCH 089/148] migrate tests --- client/keys/add.go | 2 +- crypto/keyring/keyring_test.go | 62 ++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/client/keys/add.go b/client/keys/add.go index cf6f370c9cf..56a6d0d44ed 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -172,7 +172,7 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *buf if err != nil { return err } - _, err = kb.SavePubKey(name, pk, algo) + _, err = kb.SavePubKey(name, pk, algo.Name()) if err != nil { return err } diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 6c573822961..cf0719c73ea 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -234,36 +234,38 @@ func TestSignVerifyKeyRing(t *testing.T) { require.Equal(t, "cannot sign with offline keys", err.Error()) } -// -// func TestExportImportKeyRing(t *testing.T) { -// dir, cleanup := tests.NewTestCaseDir(t) -// t.Cleanup(cleanup) -// kb, err := NewKeyring("keybasename", "test", dir, nil) -// require.NoError(t, err) -// -// info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1) -// require.NoError(t, err) -// require.Equal(t, info.GetName(), "john") -// -// john, err := kb.Get("john") -// require.NoError(t, err) -// require.Equal(t, info.GetName(), "john") -// johnAddr := info.GetPubKey().Address() -// -// armor, err := kb.Export("john") -// require.NoError(t, err) -// -// err = kb.Import("john2", armor) -// require.NoError(t, err) -// -// john2, err := kb.Get("john2") -// require.NoError(t, err) -// -// require.Equal(t, john.GetPubKey().Address(), johnAddr) -// require.Equal(t, john.GetName(), "john") -// require.Equal(t, john, john2) -// } -// +func TestExportImportKeyRing(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + t.Cleanup(cleanup) + kb, err := New("keybasename", "test", dir, nil) + require.NoError(t, err) + + info, _, err := kb.NewMnemonic("john", English, AltSecp256k1) + require.NoError(t, err) + require.Equal(t, info.GetName(), "john") + + john, err := kb.Key("john") + require.NoError(t, err) + require.Equal(t, info.GetName(), "john") + johnAddr := info.GetPubKey().Address() + + armor, err := kb.ExportPrivKeyArmor("john", "apassphrase") + require.NoError(t, err) + + err = kb.ImportPrivKey("john2", armor, "apassphrase") + require.NoError(t, err) + + john2, err := kb.Key("john2") + require.NoError(t, err) + + require.Equal(t, john.GetPubKey().Address(), johnAddr) + require.Equal(t, john.GetName(), "john") + require.Equal(t, john.GetAddress(), john2.GetAddress()) + require.Equal(t, john.GetAlgo(), john2.GetAlgo()) + require.Equal(t, john.GetPubKey(), john2.GetPubKey()) + require.Equal(t, john.GetType(), john2.GetType()) +} + // func TestExportImportPubKeyKeyRing(t *testing.T) { // dir, cleanup := tests.NewTestCaseDir(t) // t.Cleanup(cleanup) From 0b1633fe83f13bb404b682703a7d43447f1bf158 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 19:52:29 +0200 Subject: [PATCH 090/148] migrate TestExportImportPubKeyKeyRing function --- crypto/keyring/keyring_test.go | 81 +++++++++++++++++----------------- 1 file changed, 40 insertions(+), 41 deletions(-) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index cf0719c73ea..3b5693a6ab9 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -266,47 +266,46 @@ func TestExportImportKeyRing(t *testing.T) { require.Equal(t, john.GetType(), john2.GetType()) } -// func TestExportImportPubKeyKeyRing(t *testing.T) { -// dir, cleanup := tests.NewTestCaseDir(t) -// t.Cleanup(cleanup) -// kb, err := NewKeyring("keybasename", "test", dir, nil) -// require.NoError(t, err) -// algo := Secp256k1 -// -// // CreateMnemonic a private-public key pair and ensure consistency -// notPasswd := "n9y25ah7" -// info, _, err := kb.CreateMnemonic("john", English, notPasswd, algo) -// require.Nil(t, err) -// require.NotEqual(t, info, "") -// require.Equal(t, info.GetName(), "john") -// addr := info.GetPubKey().Address() -// john, err := kb.Get("john") -// require.NoError(t, err) -// require.Equal(t, john.GetName(), "john") -// require.Equal(t, john.GetPubKey().Address(), addr) -// -// // Export the public key only -// armor, err := kb.ExportPubKey("john") -// require.NoError(t, err) -// // Import it under a different name -// err = kb.ImportPubKey("john-pubkey-only", armor) -// require.NoError(t, err) -// // Ensure consistency -// john2, err := kb.Get("john-pubkey-only") -// require.NoError(t, err) -// // Compare the public keys -// require.True(t, john.GetPubKey().Equals(john2.GetPubKey())) -// // Ensure the original key hasn't changed -// john, err = kb.Get("john") -// require.NoError(t, err) -// require.Equal(t, john.GetPubKey().Address(), addr) -// require.Equal(t, john.GetName(), "john") -// -// // Ensure keys cannot be overwritten -// err = kb.ImportPubKey("john-pubkey-only", armor) -// require.NotNil(t, err) -// } -// +func TestExportImportPubKeyKeyRing(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + t.Cleanup(cleanup) + kb, err := New("keybasename", "test", dir, nil) + require.NoError(t, err) + algo := AltSecp256k1 + + // CreateMnemonic a private-public key pair and ensure consistency + info, _, err := kb.NewMnemonic("john", English, algo) + require.Nil(t, err) + require.NotEqual(t, info, "") + require.Equal(t, info.GetName(), "john") + addr := info.GetPubKey().Address() + john, err := kb.Key("john") + require.NoError(t, err) + require.Equal(t, john.GetName(), "john") + require.Equal(t, john.GetPubKey().Address(), addr) + + // Export the public key only + armor, err := kb.ExportPubKeyArmor("john") + require.NoError(t, err) + // Import it under a different name + err = kb.ImportPubKey("john-pubkey-only", armor) + require.NoError(t, err) + // Ensure consistency + john2, err := kb.Key("john-pubkey-only") + require.NoError(t, err) + // Compare the public keys + require.True(t, john.GetPubKey().Equals(john2.GetPubKey())) + // Ensure the original key hasn't changed + john, err = kb.Key("john") + require.NoError(t, err) + require.Equal(t, john.GetPubKey().Address(), addr) + require.Equal(t, john.GetName(), "john") + + // Ensure keys cannot be overwritten + err = kb.ImportPubKey("john-pubkey-only", armor) + require.NotNil(t, err) +} + // func TestExportPrivateKeyObjectKeyRing(t *testing.T) { // dir, cleanup := tests.NewTestCaseDir(t) // t.Cleanup(cleanup) From d0a59fc435dbf941870c14efc5e925288c9739c7 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 20:28:02 +0200 Subject: [PATCH 091/148] migrate some tests --- crypto/keyring/keyring_test.go | 264 ++++++++++++++++----------------- 1 file changed, 125 insertions(+), 139 deletions(-) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 3b5693a6ab9..84cf094c64c 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -5,6 +5,10 @@ import ( "strings" "testing" + "github.com/tendermint/tendermint/crypto/multisig" + "github.com/tendermint/tendermint/crypto/secp256k1" + + "github.com/cosmos/cosmos-sdk/crypto/keys/hd" tmcrypto "github.com/tendermint/tendermint/crypto" "github.com/stretchr/testify/assert" @@ -322,145 +326,127 @@ func TestExportImportPubKeyKeyRing(t *testing.T) { // require.True(t, exported.PubKey().Equals(info.GetPubKey())) // } // -// func TestAdvancedKeyManagementKeyRing(t *testing.T) { -// dir, cleanup := tests.NewTestCaseDir(t) -// t.Cleanup(cleanup) -// kb, err := NewKeyring("keybasename", "test", dir, nil) -// require.NoError(t, err) -// -// algo := Secp256k1 -// n1, n2 := "old-name", "new name" -// p1 := "1234" -// -// // make sure key works with initial password -// _, _, err = kb.CreateMnemonic(n1, English, p1, algo) -// require.Nil(t, err, "%+v", err) -// -// _, err = kb.Export(n1 + ".notreal") -// require.NotNil(t, err) -// _, err = kb.Export(" " + n1) -// require.NotNil(t, err) -// _, err = kb.Export(n1 + " ") -// require.NotNil(t, err) -// _, err = kb.Export("") -// require.NotNil(t, err) -// exported, err := kb.Export(n1) -// require.Nil(t, err, "%+v", err) -// -// // import succeeds -// err = kb.Import(n2, exported) -// require.NoError(t, err) -// -// // second import fails -// err = kb.Import(n2, exported) -// require.NotNil(t, err) -// } -// -// func TestSeedPhraseKeyRing(t *testing.T) { -// dir, cleanup := tests.NewTestCaseDir(t) -// t.Cleanup(cleanup) -// kb, err := NewKeyring("keybasename", "test", dir, nil) -// require.NoError(t, err) -// -// algo := Secp256k1 -// n1, n2 := "lost-key", "found-again" -// p1, p2 := "1234", "foobar" -// -// // make sure key works with initial password -// info, mnemonic, err := kb.CreateMnemonic(n1, English, p1, algo) -// require.Nil(t, err, "%+v", err) -// require.Equal(t, n1, info.GetName()) -// assert.NotEmpty(t, mnemonic) -// -// // now, let us delete this key -// err = kb.Delete(n1, p1, false) -// require.Nil(t, err, "%+v", err) -// _, err = kb.Get(n1) -// require.NotNil(t, err) -// -// // let us re-create it from the mnemonic-phrase -// params := *hd.NewFundraiserParams(0, sdk.CoinType, 0) -// hdPath := params.String() -// newInfo, err := kb.CreateAccount(n2, mnemonic, DefaultBIP39Passphrase, p2, hdPath, Secp256k1) -// require.NoError(t, err) -// require.Equal(t, n2, newInfo.GetName()) -// require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) -// require.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) -// } -// -// func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { -// dir, cleanup := tests.NewTestCaseDir(t) -// t.Cleanup(cleanup) -// kb, err := NewKeyring("keybasename", "test", dir, nil) -// require.NoError(t, err) -// _, _, err = kb.CreateMnemonic("john", English, "password", Secp256k1) -// require.NoError(t, err) -// -// // no error, password is irrelevant, keystr cointains ASCII armored private key -// keystr, err := kb.ExportPrivKey("john", "wrongpassword", "password") -// require.NoError(t, err) -// require.NotEmpty(t, keystr) -// -// // try import the key - wrong password -// err = kb.ImportPrivKey("john2", keystr, "somepassword") -// require.Equal(t, "failed to decrypt private key: ciphertext decryption failed", err.Error()) -// -// // try import the key with the correct password -// require.NoError(t, kb.ImportPrivKey("john2", keystr, "password")) -// -// // overwrite is not allowed -// err = kb.ImportPrivKey("john2", keystr, "password") -// require.Equal(t, "cannot overwrite key: john2", err.Error()) -// -// // try export non existing key -// _, err = kb.ExportPrivKey("john3", "wrongpassword", "password") -// require.Equal(t, "The specified item could not be found in the keyring", err.Error()) -// } -// -// func TestSupportedAlgos(t *testing.T) { -// dir, cleanup := tests.NewTestCaseDir(t) -// t.Cleanup(cleanup) -// kb, err := NewKeyring("keybasename", "test", dir, nil) -// require.NoError(t, err) -// require.Equal(t, []pubKeyType{"secp256k1"}, kb.SupportedAlgos()) -// require.Equal(t, []pubKeyType{"secp256k1"}, kb.SupportedAlgosLedger()) -// } -// -// func TestCustomDerivFuncKey(t *testing.T) { -// kb := NewInMemory(WithDeriveFunc(func(mnemonic string, bip39Passphrase, hdPath string, algo pubKeyType) ([]byte, error) { -// return nil, errors.New("cannot derive keys") -// })) -// _, _, err := kb.CreateMnemonic("test", English, "", "") -// require.Error(t, err, "cannot derive keys") -// } -// -// func TestInMemoryLanguage(t *testing.T) { -// kb := NewInMemory() -// _, _, err := kb.CreateMnemonic("something", Japanese, "no_pass", Secp256k1) -// require.Error(t, err) -// require.Equal(t, "unsupported language: only english is supported", err.Error()) -// } -// -// func TestInMemoryCreateMultisig(t *testing.T) { -// kb, err := NewKeyring("keybasename", "memory", "", nil) -// require.NoError(t, err) -// multi := multisig.PubKeyMultisigThreshold{ -// K: 1, -// PubKeys: []tmcrypto.PubKey{secp256k1.GenPrivKey().PubKey()}, -// } -// _, err = kb.CreateMulti("multi", multi) -// require.NoError(t, err) -// } -// -// func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { -// kb := NewInMemory() -// _, err := kb.CreateAccount( -// "some_account", -// "malarkey pair crucial catch public canyon evil outer stage ten gym tornado", -// "", "", CreateHDPath(0, 0).String(), Secp256k1) -// require.Error(t, err) -// require.Equal(t, "Invalid mnemonic", err.Error()) -// } +func TestAdvancedKeyManagementKeyRing(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + t.Cleanup(cleanup) + kb, err := New("keybasename", "test", dir, nil) + require.NoError(t, err) + + algo := AltSecp256k1 + n1, n2 := "old-name", "new name" + + // make sure key works with initial password + _, _, err = kb.NewMnemonic(n1, English, algo) + require.Nil(t, err, "%+v", err) + + _, err = kb.ExportPubKeyArmor(n1 + ".notreal") + require.NotNil(t, err) + _, err = kb.ExportPubKeyArmor(" " + n1) + require.NotNil(t, err) + _, err = kb.ExportPubKeyArmor(n1 + " ") + require.NotNil(t, err) + _, err = kb.ExportPubKeyArmor("") + require.NotNil(t, err) + exported, err := kb.ExportPubKeyArmor(n1) + require.Nil(t, err, "%+v", err) + + // import succeeds + err = kb.ImportPubKey(n2, exported) + require.NoError(t, err) + + // second import fails + err = kb.ImportPubKey(n2, exported) + require.NotNil(t, err) +} + +func TestSeedPhraseKeyRing(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + t.Cleanup(cleanup) + kb, err := New("keybasename", "test", dir, nil) + require.NoError(t, err) + + algo := AltSecp256k1 + n1, n2 := "lost-key", "found-again" + + // make sure key works with initial password + info, mnemonic, err := kb.NewMnemonic(n1, English, algo) + require.Nil(t, err, "%+v", err) + require.Equal(t, n1, info.GetName()) + assert.NotEmpty(t, mnemonic) + + // now, let us delete this key + err = kb.Delete(n1) + require.Nil(t, err, "%+v", err) + _, err = kb.Key(n1) + require.NotNil(t, err) + + // let us re-create it from the mnemonic-phrase + params := *hd.NewFundraiserParams(0, sdk.CoinType, 0) + hdPath := params.String() + newInfo, err := kb.NewAccount(n2, mnemonic, DefaultBIP39Passphrase, hdPath, AltSecp256k1) + require.NoError(t, err) + require.Equal(t, n2, newInfo.GetName()) + require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) + require.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) +} + +func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + t.Cleanup(cleanup) + kb, err := New("keybasename", "test", dir, nil) + require.NoError(t, err) + + _, _, err = kb.NewMnemonic("john", English, AltSecp256k1) + require.NoError(t, err) + + keystr, err := kb.ExportPrivKeyArmor("john", "somepassword") + require.NoError(t, err) + require.NotEmpty(t, keystr) + + // try import the key - wrong password + err = kb.ImportPrivKey("john2", keystr, "bad pass") + require.Equal(t, "failed to decrypt private key: ciphertext decryption failed", err.Error()) + + // try import the key with the correct password + require.NoError(t, kb.ImportPrivKey("john2", keystr, "somepassword")) + + // overwrite is not allowed + err = kb.ImportPrivKey("john2", keystr, "password") + require.Equal(t, "cannot overwrite key: john2", err.Error()) + + // try export non existing key + _, err = kb.ExportPrivKeyArmor("john3", "wrongpassword") + require.Equal(t, "The specified item could not be found in the keyring", err.Error()) +} + +func TestInMemoryLanguage(t *testing.T) { + kb := NewInMemory() + _, _, err := kb.NewMnemonic("something", Japanese, AltSecp256k1) + require.Error(t, err) + require.Equal(t, "unsupported language: only english is supported", err.Error()) +} + +func TestInMemoryCreateMultisig(t *testing.T) { + kb, err := New("keybasename", "memory", "", nil) + require.NoError(t, err) + multi := multisig.PubKeyMultisigThreshold{ + K: 1, + PubKeys: []tmcrypto.PubKey{secp256k1.GenPrivKey().PubKey()}, + } + _, err = kb.SaveMultisig("multi", multi) + require.NoError(t, err) +} + +func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { + kb := NewInMemory() + _, err := kb.NewAccount( + "some_account", + "malarkey pair crucial catch public canyon evil outer stage ten gym tornado", + "", CreateHDPath(0, 0).String(), AltSecp256k1) + require.Error(t, err) + require.Equal(t, "Invalid mnemonic", err.Error()) +} + // // func TestInMemoryCreateLedgerUnsupportedAlgo(t *testing.T) { // kb := NewInMemory() From e254e62d2ea5edca473808dadca04950fb4e91c2 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 2 Apr 2020 20:32:44 +0200 Subject: [PATCH 092/148] New interface Migrator --- client/keys/migrate.go | 20 ++++++----------- crypto/keyring/altkeyring.go | 17 +++------------ crypto/keyring/legacy.go | 8 ++----- crypto/keyring/migrator.go | 42 ++++++++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 33 deletions(-) create mode 100644 crypto/keyring/migrator.go diff --git a/client/keys/migrate.go b/client/keys/migrate.go index 840db70f10e..43d25257af5 100644 --- a/client/keys/migrate.go +++ b/client/keys/migrate.go @@ -60,21 +60,21 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { keyringServiceName := sdk.KeyringServiceName() var ( - tmpDir string - keybase keyring.Keybase + tmpDir string + migrator keyring.Migrator ) if viper.GetBool(flags.FlagDryRun) { - tmpDir, err = ioutil.TempDir("", "keybase-migrate-dryrun") + tmpDir, err = ioutil.TempDir("", "migrator-migrate-dryrun") if err != nil { return errors.Wrap(err, "failed to create temporary directory for dryrun migration") } defer os.RemoveAll(tmpDir) - keybase, err = keyring.NewKeyring(keyringServiceName, "test", tmpDir, buf) + migrator, err = keyring.NewMigrator(keyringServiceName, "test", tmpDir, buf) } else { - keybase, err = keyring.NewKeyring(keyringServiceName, viper.GetString(flags.FlagKeyringBackend), rootDir, buf) + migrator, err = keyring.NewMigrator(keyringServiceName, viper.GetString(flags.FlagKeyringBackend), rootDir, buf) } if err != nil { return errors.Wrap(err, fmt.Sprintf( @@ -92,12 +92,6 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { keyName := key.GetName() keyType := key.GetType() - // skip key if already migrated - if _, err := keybase.Get(keyName); err == nil { - cmd.PrintErrf("Key '%s (%s)' already exists; skipping ...\n", key.GetName(), keyType) - continue - } - cmd.PrintErrf("Migrating key: '%s (%s)' ...\n", key.GetName(), keyType) // allow user to skip migrating specific keys @@ -110,7 +104,7 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { } if keyType != keyring.TypeLocal { - if err := keybase.Import(keyName, legKeyInfo); err != nil { + if err := migrator.Import(keyName, legKeyInfo); err != nil { return err } @@ -130,7 +124,7 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { return err } - if err := keybase.ImportPrivKey(keyName, armoredPriv, migratePassphrase); err != nil { + if err := migrator.Import(keyName, armoredPriv); err != nil { return err } } diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 198cae7df49..61574ac7701 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -149,7 +149,7 @@ func (ks keystore) ExportPrivKeyArmorByAddress(address types.Address, encryptPas } func (ks keystore) ImportPrivKey(uid, armor, passphrase string) error { - if ks.hasKey(uid) { + if _, err := ks.Key(uid); err == nil { return fmt.Errorf("cannot overwrite key: %s", uid) } @@ -166,20 +166,9 @@ func (ks keystore) ImportPrivKey(uid, armor, passphrase string) error { return nil } -// HasKey returns whether the key exists in the keyring. -func (ks keystore) hasKey(name string) bool { - bz, _ := ks.Key(name) - return bz != nil -} - func (ks keystore) ImportPubKey(uid string, armor string) error { - bz, _ := ks.Key(uid) - if bz != nil { - pubkey := bz.GetPubKey() - - if len(pubkey.Bytes()) > 0 { - return fmt.Errorf("cannot overwrite data for name: %s", uid) - } + if _, err := ks.Key(uid); err == nil { + return fmt.Errorf("cannot overwrite key: %s", uid) } pubBytes, algo, err := crypto.UnarmorPubKeyBytes(armor) diff --git a/crypto/keyring/legacy.go b/crypto/keyring/legacy.go index 2d61f315541..e5cb7fcdc12 100644 --- a/crypto/keyring/legacy.go +++ b/crypto/keyring/legacy.go @@ -179,10 +179,6 @@ func (kb dbKeybase) ExportPrivKey(name string, decryptPassphrase string, } // Close the underlying storage. -func (kb dbKeybase) Close() error { - return kb.db.Close() -} +func (kb dbKeybase) Close() error { return kb.db.Close() } -func infoKey(name string) []byte { - return []byte(fmt.Sprintf("%s.%s", name, infoSuffix)) -} +func infoKey(name string) []byte { return []byte(fmt.Sprintf("%s.%s", name, infoSuffix)) } diff --git a/crypto/keyring/migrator.go b/crypto/keyring/migrator.go new file mode 100644 index 00000000000..06a4092ceab --- /dev/null +++ b/crypto/keyring/migrator.go @@ -0,0 +1,42 @@ +package keyring + +import ( + "fmt" + "io" + + "github.com/cosmos/cosmos-sdk/crypto" +) + +type Migrator struct { + kr keystore +} + +func NewMigrator( + appName, backend, rootDir string, userInput io.Reader, opts ...AltKeyringOption, +) (Migrator, error) { + keyring, err := New(appName, backend, rootDir, userInput, opts...) + if err != nil { + return Migrator{}, err + } + kr := keyring.(keystore) + return Migrator{kr}, nil +} + +func (m Migrator) Import(uid string, armor string) error { + _, err := m.kr.Key(uid) + if err == nil { + return fmt.Errorf("cannot overwrite key %q", uid) + } + + infoBytes, err := crypto.UnarmorInfoBytes(armor) + if err != nil { + return err + } + + info, err := unmarshalInfo(infoBytes) + if err != nil { + return err + } + + return m.kr.writeInfo(uid, info) +} From 4ba7e39f82147bfe79d539ef42ec922a3c8187af Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 20:35:22 +0200 Subject: [PATCH 093/148] solve tests --- crypto/keyring/altkeyring_test.go | 4 +- crypto/keyring/keyring_test.go | 99 +++++++++++-------------------- 2 files changed, 37 insertions(+), 66 deletions(-) diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index 015cb42f844..e918cd6c34e 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -363,7 +363,7 @@ func TestAltKeyring_ImportExportPubKey(t *testing.T) { // Should fail importing private key on existing key. err = keyring.ImportPubKey(uid, armor) - require.EqualError(t, err, fmt.Sprintf("cannot overwrite data for name: %s", uid)) + require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", uid)) newUID := otherID err = keyring.ImportPubKey(newUID, armor) @@ -386,7 +386,7 @@ func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { // Should fail importing private key on existing key. err = keyring.ImportPubKey(uid, armor) - require.EqualError(t, err, fmt.Sprintf("cannot overwrite data for name: %s", uid)) + require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", uid)) newUID := otherID err = keyring.ImportPubKey(newUID, armor) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 84cf094c64c..3335ddac4cb 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -447,70 +447,41 @@ func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { require.Equal(t, "Invalid mnemonic", err.Error()) } -// -// func TestInMemoryCreateLedgerUnsupportedAlgo(t *testing.T) { -// kb := NewInMemory() -// -// supportedLedgerAlgos := kb.SupportedAlgosLedger() -// for _, supportedAlgo := range supportedLedgerAlgos { -// if Ed25519 == supportedAlgo { -// require.FailNow(t, "Was not an unsupported algorithm") -// } -// } -// -// _, err := kb.CreateLedger("some_account", Ed25519, "cosmos", 0, 1) -// require.Error(t, err) -// require.Equal(t, "unsupported signing algo", err.Error()) -// } -// -// func TestInMemoryCreateLedger(t *testing.T) { -// kb := NewInMemory(WithSupportedAlgosLedger([]pubKeyType{Secp256k1, Ed25519})) -// -// // test_cover and test_unit will result in different answers -// // test_cover does not compile some dependencies so ledger is disabled -// // test_unit may add a ledger mock -// // both cases are acceptable -// supportedLedgerAlgos := kb.SupportedAlgosLedger() -// secpSupported := false -// edSupported := false -// for _, supportedAlgo := range supportedLedgerAlgos { -// secpSupported = secpSupported || (supportedAlgo == Secp256k1) -// edSupported = edSupported || (supportedAlgo == Ed25519) -// } -// require.True(t, secpSupported) -// require.True(t, edSupported) -// -// ledger, err := kb.CreateLedger("some_account", Secp256k1, "cosmos", 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) -// 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() -// pk, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) -// require.NoError(t, err) -// require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) -// -// // Check that restoring the key gets the same results -// restoredKey, err := kb.Get("some_account") -// require.NoError(t, err) -// require.NotNil(t, restoredKey) -// require.Equal(t, "some_account", restoredKey.GetName()) -// require.Equal(t, TypeLedger, restoredKey.GetType()) -// pubKey = restoredKey.GetPubKey() -// pk, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) -// require.NoError(t, err) -// require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) -// -// path, err := restoredKey.GetPath() -// require.NoError(t, err) -// require.Equal(t, "44'/118'/3'/0/1", path.String()) -// } +func TestInMemoryCreateLedger(t *testing.T) { + kb := NewInMemory() + + ledger, err := kb.SaveLedgerKey("some_account", AltSecp256k1, "cosmos", 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) + 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() + pk, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) + require.NoError(t, err) + require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) + + // Check that restoring the key gets the same results + restoredKey, err := kb.Key("some_account") + require.NoError(t, err) + require.NotNil(t, restoredKey) + require.Equal(t, "some_account", restoredKey.GetName()) + require.Equal(t, TypeLedger, restoredKey.GetType()) + pubKey = restoredKey.GetPubKey() + pk, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) + require.NoError(t, err) + require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) + + path, err := restoredKey.GetPath() + require.NoError(t, err) + require.Equal(t, "44'/118'/3'/0/1", path.String()) +} + // // // TestInMemoryKeyManagement makes sure we can manipulate these keys well // func TestInMemoryKeyManagement(t *testing.T) { From b90e8f27b722f651ffd82dd7b2ad8b045af7a720 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 2 Apr 2020 20:38:53 +0200 Subject: [PATCH 094/148] Rename --- client/keys/migrate.go | 2 +- crypto/keyring/migrator.go | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/client/keys/migrate.go b/client/keys/migrate.go index 43d25257af5..1d213e206a6 100644 --- a/client/keys/migrate.go +++ b/client/keys/migrate.go @@ -61,7 +61,7 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { var ( tmpDir string - migrator keyring.Migrator + migrator keyring.InfoImporter ) if viper.GetBool(flags.FlagDryRun) { diff --git a/crypto/keyring/migrator.go b/crypto/keyring/migrator.go index 06a4092ceab..3012fd28efd 100644 --- a/crypto/keyring/migrator.go +++ b/crypto/keyring/migrator.go @@ -7,22 +7,28 @@ import ( "github.com/cosmos/cosmos-sdk/crypto" ) -type Migrator struct { +// InfoImporter is implemented by those types that want to provide functions necessary +// to migrate keys from LegacyKeybase types to Keyring types. +type InfoImporter interface { + Import(uid string, armor string) error +} + +type keyringMigrator struct { kr keystore } func NewMigrator( appName, backend, rootDir string, userInput io.Reader, opts ...AltKeyringOption, -) (Migrator, error) { +) (InfoImporter, error) { keyring, err := New(appName, backend, rootDir, userInput, opts...) if err != nil { - return Migrator{}, err + return keyringMigrator{}, err } kr := keyring.(keystore) - return Migrator{kr}, nil + return keyringMigrator{kr}, nil } -func (m Migrator) Import(uid string, armor string) error { +func (m keyringMigrator) Import(uid string, armor string) error { _, err := m.kr.Key(uid) if err == nil { return fmt.Errorf("cannot overwrite key %q", uid) From 87ef1cb62875e912b092982f41655d24fb35e627 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 20:45:27 +0200 Subject: [PATCH 095/148] migrate more tests --- crypto/keyring/keyring_test.go | 184 +++++++++++++++------------------ 1 file changed, 84 insertions(+), 100 deletions(-) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 3335ddac4cb..f2dc97bcb06 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -482,106 +482,90 @@ func TestInMemoryCreateLedger(t *testing.T) { require.Equal(t, "44'/118'/3'/0/1", path.String()) } -// -// // TestInMemoryKeyManagement makes sure we can manipulate these keys well -// func TestInMemoryKeyManagement(t *testing.T) { -// // make the storage with reasonable defaults -// cstore := NewInMemory(WithSupportedAlgos([]pubKeyType{Secp256k1, Sr25519})) -// -// // Test modified supported algos -// supportedAlgos := cstore.SupportedAlgos() -// secpSupported := false -// edSupported := false -// srSupported := false -// for _, supportedAlgo := range supportedAlgos { -// secpSupported = secpSupported || (supportedAlgo == Secp256k1) -// edSupported = edSupported || (supportedAlgo == Ed25519) -// srSupported = srSupported || (supportedAlgo == Sr25519) -// } -// require.True(t, secpSupported) -// require.False(t, edSupported) -// require.True(t, srSupported) -// -// algo := Secp256k1 -// n1, n2, n3 := "personal", "business", "other" -// p1, p2 := nums, "really-secure!@#$" -// -// // Check empty state -// l, err := cstore.List() -// require.Nil(t, err) -// require.Empty(t, l) -// -// _, _, err = cstore.CreateMnemonic(n1, English, p1, Ed25519) -// require.Error(t, err, "ed25519 keys are currently not supported by keybase") -// -// // create some keys -// _, err = cstore.Get(n1) -// require.Error(t, err) -// i, _, err := cstore.CreateMnemonic(n1, English, p1, algo) -// -// require.NoError(t, err) -// require.Equal(t, n1, i.GetName()) -// _, _, err = cstore.CreateMnemonic(n2, English, p2, algo) -// require.NoError(t, err) -// -// // we can get these keys -// i2, err := cstore.Get(n2) -// require.NoError(t, err) -// _, err = cstore.Get(n3) -// require.NotNil(t, err) -// _, err = cstore.GetByAddress(accAddr(i2)) -// require.NoError(t, err) -// addr, err := sdk.AccAddressFromBech32("cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t") -// require.NoError(t, err) -// _, err = cstore.GetByAddress(addr) -// require.NotNil(t, err) -// -// // list shows them in order -// keyS, err := cstore.List() -// require.NoError(t, err) -// require.Equal(t, 2, len(keyS)) -// // note these are in alphabetical order -// require.Equal(t, n2, keyS[0].GetName()) -// require.Equal(t, n1, keyS[1].GetName()) -// require.Equal(t, i2.GetPubKey(), keyS[0].GetPubKey()) -// -// // deleting a key removes it -// err = cstore.Delete("bad name", "foo", false) -// require.NotNil(t, err) -// err = cstore.Delete(n1, p1, false) -// require.NoError(t, err) -// keyS, err = cstore.List() -// require.NoError(t, err) -// require.Equal(t, 1, len(keyS)) -// _, err = cstore.Get(n1) -// require.Error(t, err) -// -// // create an offline key -// o1 := "offline" -// priv1 := ed25519.GenPrivKey() -// pub1 := priv1.PubKey() -// i, err = cstore.CreateOffline(o1, pub1, algo) -// require.Nil(t, err) -// require.Equal(t, pub1, i.GetPubKey()) -// require.Equal(t, o1, i.GetName()) -// iOffline := i.(*offlineInfo) -// require.Equal(t, algo, iOffline.GetAlgo()) -// keyS, err = cstore.List() -// require.NoError(t, err) -// require.Equal(t, 2, len(keyS)) -// -// // delete the offline key -// err = cstore.Delete(o1, "", false) -// require.NoError(t, err) -// keyS, err = cstore.List() -// require.NoError(t, err) -// require.Equal(t, 1, len(keyS)) -// -// // addr cache gets nuked - and test skip flag -// err = cstore.Delete(n2, "", true) -// require.NoError(t, err) -// } -// +// TestInMemoryKeyManagement makes sure we can manipulate these keys well +func TestInMemoryKeyManagement(t *testing.T) { + // make the storage with reasonable defaults + cstore := NewInMemory() + + algo := AltSecp256k1 + n1, n2, n3 := "personal", "business", "other" + + // Check empty state + l, err := cstore.List() + require.Nil(t, err) + require.Empty(t, l) + + _, _, err = cstore.NewMnemonic(n1, English, notSupportedAlgo{}) + require.Error(t, err, "ed25519 keys are currently not supported by keybase") + + // create some keys + _, err = cstore.Key(n1) + require.Error(t, err) + i, _, err := cstore.NewMnemonic(n1, English, algo) + + require.NoError(t, err) + require.Equal(t, n1, i.GetName()) + _, _, err = cstore.NewMnemonic(n2, English, algo) + require.NoError(t, err) + + // we can get these keys + i2, err := cstore.Key(n2) + require.NoError(t, err) + _, err = cstore.Key(n3) + require.NotNil(t, err) + _, err = cstore.KeyByAddress(accAddr(i2)) + require.NoError(t, err) + addr, err := sdk.AccAddressFromBech32("cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t") + require.NoError(t, err) + _, err = cstore.KeyByAddress(addr) + require.NotNil(t, err) + + // list shows them in order + keyS, err := cstore.List() + require.NoError(t, err) + require.Equal(t, 2, len(keyS)) + // note these are in alphabetical order + require.Equal(t, n2, keyS[0].GetName()) + require.Equal(t, n1, keyS[1].GetName()) + require.Equal(t, i2.GetPubKey(), keyS[0].GetPubKey()) + + // deleting a key removes it + err = cstore.Delete("bad name") + require.NotNil(t, err) + err = cstore.Delete(n1) + require.NoError(t, err) + keyS, err = cstore.List() + require.NoError(t, err) + require.Equal(t, 1, len(keyS)) + _, err = cstore.Key(n1) + require.Error(t, err) + + // create an offline key + o1 := "offline" + priv1 := ed25519.GenPrivKey() + pub1 := priv1.PubKey() + i, err = cstore.SavePubKey(o1, pub1, Ed25519) + require.Nil(t, err) + require.Equal(t, pub1, i.GetPubKey()) + require.Equal(t, o1, i.GetName()) + iOffline := i.(*offlineInfo) + require.Equal(t, Ed25519, iOffline.GetAlgo()) + keyS, err = cstore.List() + require.NoError(t, err) + require.Equal(t, 2, len(keyS)) + + // delete the offline key + err = cstore.Delete(o1) + require.NoError(t, err) + keyS, err = cstore.List() + require.NoError(t, err) + require.Equal(t, 1, len(keyS)) + + // addr cache gets nuked - and test skip flag + err = cstore.Delete(n2) + require.NoError(t, err) +} + // // TestInMemorySignVerify does some detailed checks on how we sign and validate // // signatures // func TestInMemorySignVerify(t *testing.T) { From 36cc921a9b3afdf14c66ceede81a86e8eb34bf19 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 20:48:08 +0200 Subject: [PATCH 096/148] migrate tests --- crypto/keyring/keyring_test.go | 153 ++++++++++++++++----------------- 1 file changed, 76 insertions(+), 77 deletions(-) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index f2dc97bcb06..91f54dc4b91 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -566,83 +566,82 @@ func TestInMemoryKeyManagement(t *testing.T) { require.NoError(t, err) } -// // TestInMemorySignVerify does some detailed checks on how we sign and validate -// // signatures -// func TestInMemorySignVerify(t *testing.T) { -// cstore := NewInMemory() -// algo := Secp256k1 -// -// n1, n2, n3 := "some dude", "a dudette", "dude-ish" -// p1, p2, p3 := nums, foobar, foobar -// -// // create two users and get their info -// i1, _, err := cstore.CreateMnemonic(n1, English, p1, algo) -// require.Nil(t, err) -// -// i2, _, err := cstore.CreateMnemonic(n2, English, p2, algo) -// require.Nil(t, err) -// -// // Import a public key -// armor, err := cstore.ExportPubKey(n2) -// require.Nil(t, err) -// err = cstore.ImportPubKey(n3, armor) -// require.NoError(t, err) -// i3, err := cstore.Get(n3) -// require.NoError(t, err) -// require.Equal(t, i3.GetName(), n3) -// -// // let's try to sign some messages -// d1 := []byte("my first message") -// d2 := []byte("some other important info!") -// d3 := []byte("feels like I forgot something...") -// -// // try signing both data with both .. -// s11, pub1, err := cstore.Sign(n1, p1, d1) -// require.Nil(t, err) -// require.Equal(t, i1.GetPubKey(), pub1) -// -// s12, pub1, err := cstore.Sign(n1, p1, d2) -// require.Nil(t, err) -// require.Equal(t, i1.GetPubKey(), pub1) -// -// s21, pub2, err := cstore.Sign(n2, p2, d1) -// require.Nil(t, err) -// require.Equal(t, i2.GetPubKey(), pub2) -// -// s22, pub2, err := cstore.Sign(n2, p2, d2) -// require.Nil(t, err) -// require.Equal(t, i2.GetPubKey(), pub2) -// -// // let's try to validate and make sure it only works when everything is proper -// cases := []struct { -// key tmcrypto.PubKey -// data []byte -// sig []byte -// valid bool -// }{ -// // proper matches -// {i1.GetPubKey(), d1, s11, true}, -// // change data, pubkey, or signature leads to fail -// {i1.GetPubKey(), d2, s11, false}, -// {i2.GetPubKey(), d1, s11, false}, -// {i1.GetPubKey(), d1, s21, false}, -// // make sure other successes -// {i1.GetPubKey(), d2, s12, true}, -// {i2.GetPubKey(), d1, s21, true}, -// {i2.GetPubKey(), d2, s22, true}, -// } -// -// for i, tc := range cases { -// valid := tc.key.VerifyBytes(tc.data, tc.sig) -// require.Equal(t, tc.valid, valid, "%d", i) -// } -// -// // Now try to sign data with a secret-less key -// _, _, err = cstore.Sign(n3, p3, d3) -// require.Error(t, err) -// require.Equal(t, "cannot sign with offline keys", err.Error()) -// } -// +// TestInMemorySignVerify does some detailed checks on how we sign and validate +// signatures +func TestInMemorySignVerify(t *testing.T) { + cstore := NewInMemory() + algo := AltSecp256k1 + + n1, n2, n3 := "some dude", "a dudette", "dude-ish" + + // create two users and get their info + i1, _, err := cstore.NewMnemonic(n1, English, algo) + require.Nil(t, err) + + i2, _, err := cstore.NewMnemonic(n2, English, algo) + require.Nil(t, err) + + // Import a public key + armor, err := cstore.ExportPubKeyArmor(n2) + require.Nil(t, err) + err = cstore.ImportPubKey(n3, armor) + require.NoError(t, err) + i3, err := cstore.Key(n3) + require.NoError(t, err) + require.Equal(t, i3.GetName(), n3) + + // let's try to sign some messages + d1 := []byte("my first message") + d2 := []byte("some other important info!") + d3 := []byte("feels like I forgot something...") + + // try signing both data with both .. + s11, pub1, err := cstore.Sign(n1, d1) + require.Nil(t, err) + require.Equal(t, i1.GetPubKey(), pub1) + + s12, pub1, err := cstore.Sign(n1, d2) + require.Nil(t, err) + require.Equal(t, i1.GetPubKey(), pub1) + + s21, pub2, err := cstore.Sign(n2, d1) + require.Nil(t, err) + require.Equal(t, i2.GetPubKey(), pub2) + + s22, pub2, err := cstore.Sign(n2, d2) + require.Nil(t, err) + require.Equal(t, i2.GetPubKey(), pub2) + + // let's try to validate and make sure it only works when everything is proper + cases := []struct { + key tmcrypto.PubKey + data []byte + sig []byte + valid bool + }{ + // proper matches + {i1.GetPubKey(), d1, s11, true}, + // change data, pubkey, or signature leads to fail + {i1.GetPubKey(), d2, s11, false}, + {i2.GetPubKey(), d1, s11, false}, + {i1.GetPubKey(), d1, s21, false}, + // make sure other successes + {i1.GetPubKey(), d2, s12, true}, + {i2.GetPubKey(), d1, s21, true}, + {i2.GetPubKey(), d2, s22, true}, + } + + for i, tc := range cases { + valid := tc.key.VerifyBytes(tc.data, tc.sig) + require.Equal(t, tc.valid, valid, "%d", i) + } + + // Now try to sign data with a secret-less key + _, _, err = cstore.Sign(n3, d3) + require.Error(t, err) + require.Equal(t, "cannot sign with offline keys", err.Error()) +} + // // TestInMemoryExportImport tests exporting and importing // func TestInMemoryExportImport(t *testing.T) { // // make the storage with reasonable defaults From 88489da57ebf99459ab8c61649671e2987913eaf Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 2 Apr 2020 20:55:42 +0200 Subject: [PATCH 097/148] Add tests --- client/keys/migrate.go | 4 +-- crypto/keyring/legacy.go | 42 ++++++++++++++++++++++++++++++ crypto/keyring/legacy_test.go | 4 +++ crypto/keyring/migrator.go | 48 ----------------------------------- 4 files changed, 48 insertions(+), 50 deletions(-) delete mode 100644 crypto/keyring/migrator.go diff --git a/client/keys/migrate.go b/client/keys/migrate.go index 1d213e206a6..12dc313e5f2 100644 --- a/client/keys/migrate.go +++ b/client/keys/migrate.go @@ -72,9 +72,9 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { defer os.RemoveAll(tmpDir) - migrator, err = keyring.NewMigrator(keyringServiceName, "test", tmpDir, buf) + migrator, err = keyring.NewInfoImporter(keyringServiceName, "test", tmpDir, buf) } else { - migrator, err = keyring.NewMigrator(keyringServiceName, viper.GetString(flags.FlagKeyringBackend), rootDir, buf) + migrator, err = keyring.NewInfoImporter(keyringServiceName, viper.GetString(flags.FlagKeyringBackend), rootDir, buf) } if err != nil { return errors.Wrap(err, fmt.Sprintf( diff --git a/crypto/keyring/legacy.go b/crypto/keyring/legacy.go index e5cb7fcdc12..13cd88ab67b 100644 --- a/crypto/keyring/legacy.go +++ b/crypto/keyring/legacy.go @@ -2,6 +2,7 @@ package keyring import ( "fmt" + "io" "strings" "github.com/pkg/errors" @@ -182,3 +183,44 @@ func (kb dbKeybase) ExportPrivKey(name string, decryptPassphrase string, func (kb dbKeybase) Close() error { return kb.db.Close() } func infoKey(name string) []byte { return []byte(fmt.Sprintf("%s.%s", name, infoSuffix)) } + +// InfoImporter is implemented by those types that want to provide functions necessary +// to migrate keys from LegacyKeybase types to Keyring types. +type InfoImporter interface { + // Import imports ASCII-armored private keys. + Import(uid string, armor string) error +} + +type keyringMigrator struct { + kr keystore +} + +func NewInfoImporter( + appName, backend, rootDir string, userInput io.Reader, opts ...AltKeyringOption, +) (InfoImporter, error) { + keyring, err := New(appName, backend, rootDir, userInput, opts...) + if err != nil { + return keyringMigrator{}, err + } + kr := keyring.(keystore) + return keyringMigrator{kr}, nil +} + +func (m keyringMigrator) Import(uid string, armor string) error { + _, err := m.kr.Key(uid) + if err == nil { + return fmt.Errorf("cannot overwrite key %q", uid) + } + + infoBytes, err := crypto.UnarmorInfoBytes(armor) + if err != nil { + return err + } + + info, err := unmarshalInfo(infoBytes) + if err != nil { + return err + } + + return m.kr.writeInfo(uid, info) +} diff --git a/crypto/keyring/legacy_test.go b/crypto/keyring/legacy_test.go index 1e2b475660b..5a7ef869e0b 100644 --- a/crypto/keyring/legacy_test.go +++ b/crypto/keyring/legacy_test.go @@ -41,4 +41,8 @@ func TestLegacyKeybase(t *testing.T) { armoredInfo, err := kb.Export(keys[0].GetName()) require.NoError(t, err) require.NotEmpty(t, armoredInfo) + + importer, err := keyring.NewInfoImporter("cosmos", "memory", "", nil) + require.NoError(t, err) + require.NoError(t, importer.Import("test", armoredInfo)) } diff --git a/crypto/keyring/migrator.go b/crypto/keyring/migrator.go deleted file mode 100644 index 3012fd28efd..00000000000 --- a/crypto/keyring/migrator.go +++ /dev/null @@ -1,48 +0,0 @@ -package keyring - -import ( - "fmt" - "io" - - "github.com/cosmos/cosmos-sdk/crypto" -) - -// InfoImporter is implemented by those types that want to provide functions necessary -// to migrate keys from LegacyKeybase types to Keyring types. -type InfoImporter interface { - Import(uid string, armor string) error -} - -type keyringMigrator struct { - kr keystore -} - -func NewMigrator( - appName, backend, rootDir string, userInput io.Reader, opts ...AltKeyringOption, -) (InfoImporter, error) { - keyring, err := New(appName, backend, rootDir, userInput, opts...) - if err != nil { - return keyringMigrator{}, err - } - kr := keyring.(keystore) - return keyringMigrator{kr}, nil -} - -func (m keyringMigrator) Import(uid string, armor string) error { - _, err := m.kr.Key(uid) - if err == nil { - return fmt.Errorf("cannot overwrite key %q", uid) - } - - infoBytes, err := crypto.UnarmorInfoBytes(armor) - if err != nil { - return err - } - - info, err := unmarshalInfo(infoBytes) - if err != nil { - return err - } - - return m.kr.writeInfo(uid, info) -} From 6432e55879a4df0dea0e6ae5197895e072fdda46 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 21:06:27 +0200 Subject: [PATCH 098/148] migrate more tests --- crypto/keyring/keyring_test.go | 111 +++++++++++++++++---------------- 1 file changed, 56 insertions(+), 55 deletions(-) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 91f54dc4b91..a2d648b2cd4 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -642,61 +642,62 @@ func TestInMemorySignVerify(t *testing.T) { require.Equal(t, "cannot sign with offline keys", err.Error()) } -// // TestInMemoryExportImport tests exporting and importing -// func TestInMemoryExportImport(t *testing.T) { -// // make the storage with reasonable defaults -// cstore := NewInMemory() -// -// info, _, err := cstore.CreateMnemonic("john", English, "secretcpw", Secp256k1) -// require.NoError(t, err) -// require.Equal(t, info.GetName(), "john") -// -// john, err := cstore.Get("john") -// require.NoError(t, err) -// require.Equal(t, info.GetName(), "john") -// johnAddr := info.GetPubKey().Address() -// -// armor, err := cstore.Export("john") -// require.NoError(t, err) -// -// err = cstore.Import("john2", armor) -// require.NoError(t, err) -// -// john2, err := cstore.Get("john2") -// require.NoError(t, err) -// -// require.Equal(t, john.GetPubKey().Address(), johnAddr) -// require.Equal(t, john.GetName(), "john") -// require.Equal(t, john, john2) -// } -// -// func TestInMemoryExportImportPrivKey(t *testing.T) { -// kb := NewInMemory() -// -// info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1) -// require.NoError(t, err) -// require.Equal(t, info.GetName(), "john") -// priv1, err := kb.Get("john") -// require.NoError(t, err) -// -// // decrypt local private key, and produce encrypted ASCII armored output -// armored, err := kb.ExportPrivKey("john", "secretcpw", "new_secretcpw") -// require.NoError(t, err) -// -// // delete exported key -// require.NoError(t, kb.Delete("john", "", true)) -// _, err = kb.Get("john") -// require.Error(t, err) -// -// // import armored key -// require.NoError(t, kb.ImportPrivKey("john", armored, "new_secretcpw")) -// -// // ensure old and new keys match -// priv2, err := kb.Get("john") -// require.NoError(t, err) -// require.True(t, priv1.GetPubKey().Equals(priv2.GetPubKey())) -// } -// +// TestInMemoryExportImport tests exporting and importing +func TestInMemoryExportImport(t *testing.T) { + // make the storage with reasonable defaults + cstore := NewInMemory() + + info, _, err := cstore.NewMnemonic("john", English, AltSecp256k1) + require.NoError(t, err) + require.Equal(t, info.GetName(), "john") + + john, err := cstore.Key("john") + require.NoError(t, err) + require.Equal(t, info.GetName(), "john") + johnAddr := info.GetPubKey().Address() + + armor, err := cstore.ExportPubKeyArmor("john") + require.NoError(t, err) + + err = cstore.ImportPubKey("john2", armor) + require.NoError(t, err) + + john2, err := cstore.Key("john2") + require.NoError(t, err) + + require.Equal(t, john.GetPubKey().Address(), johnAddr) + require.Equal(t, john.GetName(), "john") + require.Equal(t, john.GetAddress(), john2.GetAddress()) + require.Equal(t, john.GetAlgo(), john2.GetAlgo()) + require.Equal(t, john.GetPubKey(), john2.GetPubKey()) +} + +func TestInMemoryExportImportPrivKey(t *testing.T) { + kb := NewInMemory() + + info, _, err := kb.NewMnemonic("john", English, AltSecp256k1) + require.NoError(t, err) + require.Equal(t, info.GetName(), "john") + priv1, err := kb.Key("john") + require.NoError(t, err) + + armored, err := kb.ExportPrivKeyArmor("john", "secretcpw") + require.NoError(t, err) + + // delete exported key + require.NoError(t, kb.Delete("john")) + _, err = kb.Key("john") + require.Error(t, err) + + // import armored key + require.NoError(t, kb.ImportPrivKey("john", armored, "secretcpw")) + + // ensure old and new keys match + priv2, err := kb.Key("john") + require.NoError(t, err) + require.True(t, priv1.GetPubKey().Equals(priv2.GetPubKey())) +} + // func TestInMemoryExportImportPubKey(t *testing.T) { // // make the storage with reasonable defaults // cstore := NewInMemory() From 29214ef651c98ccb6012fbe2ab7d31b27f1a9c4c Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 21:10:06 +0200 Subject: [PATCH 099/148] migrate more tests --- crypto/keyring/keyring_test.go | 75 +++++++++++++++++----------------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index a2d648b2cd4..011b885b554 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -698,44 +698,43 @@ func TestInMemoryExportImportPrivKey(t *testing.T) { require.True(t, priv1.GetPubKey().Equals(priv2.GetPubKey())) } -// func TestInMemoryExportImportPubKey(t *testing.T) { -// // make the storage with reasonable defaults -// cstore := NewInMemory() -// -// // CreateMnemonic a private-public key pair and ensure consistency -// notPasswd := "n9y25ah7" -// info, _, err := cstore.CreateMnemonic("john", English, notPasswd, Secp256k1) -// require.Nil(t, err) -// require.NotEqual(t, info, "") -// require.Equal(t, info.GetName(), "john") -// addr := info.GetPubKey().Address() -// john, err := cstore.Get("john") -// require.NoError(t, err) -// require.Equal(t, john.GetName(), "john") -// require.Equal(t, john.GetPubKey().Address(), addr) -// -// // Export the public key only -// armor, err := cstore.ExportPubKey("john") -// require.NoError(t, err) -// // Import it under a different name -// err = cstore.ImportPubKey("john-pubkey-only", armor) -// require.NoError(t, err) -// // Ensure consistency -// john2, err := cstore.Get("john-pubkey-only") -// require.NoError(t, err) -// // Compare the public keys -// require.True(t, john.GetPubKey().Equals(john2.GetPubKey())) -// // Ensure the original key hasn't changed -// john, err = cstore.Get("john") -// require.NoError(t, err) -// require.Equal(t, john.GetPubKey().Address(), addr) -// require.Equal(t, john.GetName(), "john") -// -// // Ensure keys cannot be overwritten -// err = cstore.ImportPubKey("john-pubkey-only", armor) -// require.NotNil(t, err) -// } -// +func TestInMemoryExportImportPubKey(t *testing.T) { + // make the storage with reasonable defaults + cstore := NewInMemory() + + // CreateMnemonic a private-public key pair and ensure consistency + info, _, err := cstore.NewMnemonic("john", English, AltSecp256k1) + require.Nil(t, err) + require.NotEqual(t, info, "") + require.Equal(t, info.GetName(), "john") + addr := info.GetPubKey().Address() + john, err := cstore.Key("john") + require.NoError(t, err) + require.Equal(t, john.GetName(), "john") + require.Equal(t, john.GetPubKey().Address(), addr) + + // Export the public key only + armor, err := cstore.ExportPubKeyArmor("john") + require.NoError(t, err) + // Import it under a different name + err = cstore.ImportPubKey("john-pubkey-only", armor) + require.NoError(t, err) + // Ensure consistency + john2, err := cstore.Key("john-pubkey-only") + require.NoError(t, err) + // Compare the public keys + require.True(t, john.GetPubKey().Equals(john2.GetPubKey())) + // Ensure the original key hasn't changed + john, err = cstore.Key("john") + require.NoError(t, err) + require.Equal(t, john.GetPubKey().Address(), addr) + require.Equal(t, john.GetName(), "john") + + // Ensure keys cannot be overwritten + err = cstore.ImportPubKey("john-pubkey-only", armor) + require.NotNil(t, err) +} + // func TestInMemoryExportPrivateKeyObject(t *testing.T) { // kb := NewInMemory() // From 40b32b660284e078ae8170cb0bf70ff707b96bbc Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 21:11:07 +0200 Subject: [PATCH 100/148] remove export object --- crypto/keyring/keyring_test.go | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 011b885b554..17973d49b54 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -310,22 +310,6 @@ func TestExportImportPubKeyKeyRing(t *testing.T) { require.NotNil(t, err) } -// func TestExportPrivateKeyObjectKeyRing(t *testing.T) { -// dir, cleanup := tests.NewTestCaseDir(t) -// t.Cleanup(cleanup) -// kb, err := NewKeyring("keybasename", "test", dir, nil) -// require.NoError(t, err) -// -// info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1) -// require.NoError(t, err) -// require.Equal(t, info.GetName(), "john") -// -// // export private key object -// exported, err := kb.ExportPrivateKeyObject("john", "secretcpw") -// require.Nil(t, err, "%+v", err) -// require.True(t, exported.PubKey().Equals(info.GetPubKey())) -// } -// func TestAdvancedKeyManagementKeyRing(t *testing.T) { dir, cleanup := tests.NewTestCaseDir(t) t.Cleanup(cleanup) @@ -735,21 +719,6 @@ func TestInMemoryExportImportPubKey(t *testing.T) { require.NotNil(t, err) } -// func TestInMemoryExportPrivateKeyObject(t *testing.T) { -// kb := NewInMemory() -// -// info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1) -// require.NoError(t, err) -// require.Equal(t, info.GetName(), "john") -// -// // export private key object -// _, err = kb.ExportPrivateKeyObject("john", "invalid") -// require.NoError(t, err, "%+v", err) -// exported, err := kb.ExportPrivateKeyObject("john", "secretcpw") -// require.Nil(t, err, "%+v", err) -// require.True(t, exported.PubKey().Equals(info.GetPubKey())) -// } -// // // TestInMemoryAdvancedKeyManagement verifies update, import, export functionality // func TestInMemoryAdvancedKeyManagement(t *testing.T) { // // make the storage with reasonable defaults From 2fbd136dec12bf21af355df303518e50e522836a Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 21:15:57 +0200 Subject: [PATCH 101/148] migrate more tests --- crypto/keyring/keyring_test.go | 67 +++++++++++++++++----------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 17973d49b54..2eeafe91519 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -719,40 +719,39 @@ func TestInMemoryExportImportPubKey(t *testing.T) { require.NotNil(t, err) } -// // TestInMemoryAdvancedKeyManagement verifies update, import, export functionality -// func TestInMemoryAdvancedKeyManagement(t *testing.T) { -// // make the storage with reasonable defaults -// cstore := NewInMemory() -// -// algo := Secp256k1 -// n1, n2 := "old-name", "new name" -// p1 := nums -// -// // make sure key works with initial password -// _, _, err := cstore.CreateMnemonic(n1, English, p1, algo) -// require.Nil(t, err, "%+v", err) -// -// // exporting requires the proper name and passphrase -// _, err = cstore.Export(n1 + ".notreal") -// require.NotNil(t, err) -// _, err = cstore.Export(" " + n1) -// require.NotNil(t, err) -// _, err = cstore.Export(n1 + " ") -// require.NotNil(t, err) -// _, err = cstore.Export("") -// require.NotNil(t, err) -// exported, err := cstore.Export(n1) -// require.Nil(t, err, "%+v", err) -// -// // import succeeds -// err = cstore.Import(n2, exported) -// require.NoError(t, err) -// -// // second import fails -// err = cstore.Import(n2, exported) -// require.NotNil(t, err) -// } -// +// TestInMemoryAdvancedKeyManagement verifies update, import, export functionality +func TestInMemoryAdvancedKeyManagement(t *testing.T) { + // make the storage with reasonable defaults + cstore := NewInMemory() + + algo := AltSecp256k1 + n1, n2 := "old-name", "new name" + + // make sure key works with initial password + _, _, err := cstore.NewMnemonic(n1, English, algo) + require.Nil(t, err, "%+v", err) + + // exporting requires the proper name and passphrase + _, err = cstore.ExportPubKeyArmor(n1 + ".notreal") + require.NotNil(t, err) + _, err = cstore.ExportPubKeyArmor(" " + n1) + require.NotNil(t, err) + _, err = cstore.ExportPubKeyArmor(n1 + " ") + require.NotNil(t, err) + _, err = cstore.ExportPubKeyArmor("") + require.NotNil(t, err) + exported, err := cstore.ExportPubKeyArmor(n1) + require.Nil(t, err, "%+v", err) + + // import succeeds + err = cstore.ImportPubKey(n2, exported) + require.NoError(t, err) + + // second import fails + err = cstore.ImportPubKey(n2, exported) + require.NotNil(t, err) +} + // // TestInMemorySeedPhrase verifies restoring from a seed phrase // func TestInMemorySeedPhrase(t *testing.T) { // From 095fcb79dbf15eb18fabd9e692dfabb5f933aa62 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 21:18:18 +0200 Subject: [PATCH 102/148] migrate unit tests --- crypto/keyring/keyring_test.go | 63 +++++++++++++++++----------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 2eeafe91519..7fc2c6f0dec 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -752,38 +752,37 @@ func TestInMemoryAdvancedKeyManagement(t *testing.T) { require.NotNil(t, err) } -// // TestInMemorySeedPhrase verifies restoring from a seed phrase -// func TestInMemorySeedPhrase(t *testing.T) { -// -// // make the storage with reasonable defaults -// cstore := NewInMemory() -// -// algo := Secp256k1 -// n1, n2 := "lost-key", "found-again" -// p1, p2 := nums, foobar -// -// // make sure key works with initial password -// info, mnemonic, err := cstore.CreateMnemonic(n1, English, p1, algo) -// require.Nil(t, err, "%+v", err) -// require.Equal(t, n1, info.GetName()) -// require.NotEmpty(t, mnemonic) -// -// // now, let us delete this key -// err = cstore.Delete(n1, p1, false) -// require.Nil(t, err, "%+v", err) -// _, err = cstore.Get(n1) -// require.NotNil(t, err) -// -// // let us re-create it from the mnemonic-phrase -// params := *hd.NewFundraiserParams(0, sdk.CoinType, 0) -// hdPath := params.String() -// newInfo, err := cstore.CreateAccount(n2, mnemonic, DefaultBIP39Passphrase, p2, hdPath, Secp256k1) -// require.NoError(t, err) -// require.Equal(t, n2, newInfo.GetName()) -// require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) -// require.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) -// } -// +// TestInMemorySeedPhrase verifies restoring from a seed phrase +func TestInMemorySeedPhrase(t *testing.T) { + + // make the storage with reasonable defaults + cstore := NewInMemory() + + algo := AltSecp256k1 + n1, n2 := "lost-key", "found-again" + + // make sure key works with initial password + info, mnemonic, err := cstore.NewMnemonic(n1, English, algo) + require.Nil(t, err, "%+v", err) + require.Equal(t, n1, info.GetName()) + require.NotEmpty(t, mnemonic) + + // now, let us delete this key + err = cstore.Delete(n1) + require.Nil(t, err, "%+v", err) + _, err = cstore.Key(n1) + require.NotNil(t, err) + + // let us re-create it from the mnemonic-phrase + params := *hd.NewFundraiserParams(0, sdk.CoinType, 0) + hdPath := params.String() + newInfo, err := cstore.NewAccount(n2, mnemonic, DefaultBIP39Passphrase, hdPath, algo) + require.NoError(t, err) + require.Equal(t, n2, newInfo.GetName()) + require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) + require.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) +} + // func ExampleNew() { // // Select the encryption and storage for your cryptostore // customKeyGenFunc := func(bz []byte, algo pubKeyType) (tmcrypto.PrivKey, error) { From 1c376471bed00b185403a3ab9de4adf515209d2c Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Thu, 2 Apr 2020 21:24:30 +0200 Subject: [PATCH 103/148] end migrate tests --- crypto/keyring/keyring_test.go | 179 ++++++++++----------------------- 1 file changed, 52 insertions(+), 127 deletions(-) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 7fc2c6f0dec..ab88c7e7821 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -2,6 +2,7 @@ package keyring import ( "bytes" + "fmt" "strings" "testing" @@ -783,132 +784,56 @@ func TestInMemorySeedPhrase(t *testing.T) { require.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) } -// func ExampleNew() { -// // Select the encryption and storage for your cryptostore -// customKeyGenFunc := func(bz []byte, algo pubKeyType) (tmcrypto.PrivKey, error) { -// var bzArr [32]byte -// copy(bzArr[:], bz) -// return secp256k1.PrivKeySecp256k1(bzArr), nil -// } -// cstore := NewInMemory(WithKeygenFunc(customKeyGenFunc)) -// -// sec := Secp256k1 -// -// // Add keys and see they return in alphabetical order -// bob, _, err := cstore.CreateMnemonic("Bob", English, "friend", sec) -// if err != nil { -// // this should never happen -// fmt.Println(err) -// } else { -// // return info here just like in List -// fmt.Println(bob.GetName()) -// } -// _, _, _ = cstore.CreateMnemonic("Alice", English, "secret", sec) -// _, _, _ = cstore.CreateMnemonic("Carl", English, "mitm", sec) -// info, _ := cstore.List() -// for _, i := range info { -// fmt.Println(i.GetName()) -// } -// -// // We need to use passphrase to generate a signature -// tx := []byte("deadbeef") -// sig, pub, err := cstore.Sign("Bob", "friend", tx) -// if err != nil { -// fmt.Println("don't accept real passphrase") -// } -// -// // and we can validate the signature with publicly available info -// binfo, _ := cstore.Get("Bob") -// if !binfo.GetPubKey().Equals(bob.GetPubKey()) { -// fmt.Println("Get and Create return different keys") -// } -// -// if pub.Equals(binfo.GetPubKey()) { -// fmt.Println("signed by Bob") -// } -// if !pub.VerifyBytes(tx, sig) { -// fmt.Println("invalid signature") -// } -// -// // Output: -// // Bob -// // Alice -// // Bob -// // Carl -// // signed by Bob -// } -// -func accAddr(info Info) sdk.AccAddress { - return (sdk.AccAddress)(info.GetPubKey().Address()) +func ExampleNew() { + // Select the encryption and storage for your cryptostore + cstore := NewInMemory() + + sec := AltSecp256k1 + + // Add keys and see they return in alphabetical order + bob, _, err := cstore.NewMnemonic("Bob", English, sec) + if err != nil { + // this should never happen + fmt.Println(err) + } else { + // return info here just like in List + fmt.Println(bob.GetName()) + } + _, _, _ = cstore.NewMnemonic("Alice", English, sec) + _, _, _ = cstore.NewMnemonic("Carl", English, sec) + info, _ := cstore.List() + for _, i := range info { + fmt.Println(i.GetName()) + } + + // We need to use passphrase to generate a signature + tx := []byte("deadbeef") + sig, pub, err := cstore.Sign("Bob", tx) + if err != nil { + fmt.Println("don't accept real passphrase") + } + + // and we can validate the signature with publicly available info + binfo, _ := cstore.Key("Bob") + if !binfo.GetPubKey().Equals(bob.GetPubKey()) { + fmt.Println("Get and Create return different keys") + } + + if pub.Equals(binfo.GetPubKey()) { + fmt.Println("signed by Bob") + } + if !pub.VerifyBytes(tx, sig) { + fmt.Println("invalid signature") + } + + // Output: + // Bob + // Alice + // Bob + // Carl + // signed by Bob } -// var _ tmcrypto.PrivKey = testPriv{} -// var _ tmcrypto.PubKey = testPub{} -// var testCdc *amino.Codec -// -// type testPriv []byte -// -// func (privkey testPriv) PubKey() tmcrypto.PubKey { return testPub{} } -// func (privkey testPriv) Bytes() []byte { -// return testCdc.MustMarshalBinaryBare(privkey) -// } -// func (privkey testPriv) Sign(msg []byte) ([]byte, error) { return []byte{}, nil } -// func (privkey testPriv) Equals(other tmcrypto.PrivKey) bool { return true } -// -// type testPub []byte -// -// func (key testPub) Address() tmcrypto.Address { return tmcrypto.Address{} } -// func (key testPub) Bytes() []byte { -// return testCdc.MustMarshalBinaryBare(key) -// } -// func (key testPub) VerifyBytes(msg []byte, sig []byte) bool { return true } -// func (key testPub) Equals(other tmcrypto.PubKey) bool { return true } -// -// func TestInMemoryKeygenOverride(t *testing.T) { -// // Save existing codec and reset after test -// cryptoCdc := CryptoCdc -// t.Cleanup(func() { -// CryptoCdc = cryptoCdc -// }) -// -// // Setup testCdc encoding and decoding new key type -// testCdc = codec.New() -// RegisterCodec(testCdc) -// tmamino.RegisterAmino(testCdc) -// -// // Set up codecs for using new key types -// privName, pubName := "test/priv_name", "test/pub_name" -// tmamino.RegisterKeyType(testPriv{}, privName) -// tmamino.RegisterKeyType(testPub{}, pubName) -// testCdc.RegisterConcrete(testPriv{}, privName, nil) -// testCdc.RegisterConcrete(testPub{}, pubName, nil) -// CryptoCdc = testCdc -// -// overrideCalled := false -// dummyFunc := func(bz []byte, algo pubKeyType) (tmcrypto.PrivKey, error) { -// overrideCalled = true -// return testPriv(bz), nil -// } -// -// kb := NewInMemory(WithKeygenFunc(dummyFunc)) -// -// testName, pw := "name", "testPassword" -// -// // create new key which will generate with -// info, _, err := kb.CreateMnemonic(testName, English, pw, Secp256k1) -// require.NoError(t, err) -// require.Equal(t, info.GetName(), testName) -// -// // Assert overridden function was called -// require.True(t, overrideCalled) -// -// // export private key object -// exported, err := kb.ExportPrivateKeyObject(testName, pw) -// require.Nil(t, err, "%+v", err) -// -// // require that the key type is the new key -// _, ok := exported.(testPriv) -// require.True(t, ok) -// -// require.True(t, exported.PubKey().Equals(info.GetPubKey())) -// } +func accAddr(info Info) sdk.AccAddress { + return sdk.AccAddress(info.GetPubKey().Address()) +} From 97f6c8e3e37a3e01e197c054a95a3e4cf4cbf366 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 2 Apr 2020 22:28:53 +0200 Subject: [PATCH 104/148] Update client tests --- client/keys/add_ledger_test.go | 6 +- client/keys/add_test.go | 6 +- client/keys/delete.go | 8 +- client/keys/delete_test.go | 21 +- client/keys/export_test.go | 7 +- client/keys/import_test.go | 4 +- client/keys/list_test.go | 7 +- client/keys/show_test.go | 15 +- crypto/keyring/altkeyring.go | 5 + crypto/keyring/altkeyring_test.go | 834 ++++++++++++++++++++++++++++- crypto/keyring/keyring.go | 7 - crypto/keyring/keyring_test.go | 839 ------------------------------ 12 files changed, 870 insertions(+), 889 deletions(-) delete mode 100644 crypto/keyring/keyring_test.go diff --git a/client/keys/add_ledger_test.go b/client/keys/add_ledger_test.go index b21a0b1850d..2fd57286996 100644 --- a/client/keys/add_ledger_test.go +++ b/client/keys/add_ledger_test.go @@ -93,14 +93,14 @@ func Test_runAddCmdLedger(t *testing.T) { require.NoError(t, runAddCmd(cmd, []string{"keyname1"})) // Now check that it has been stored properly - kb, err := keyring.NewKeyring(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), kbHome, mockIn) + kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), kbHome, mockIn) require.NoError(t, err) require.NotNil(t, kb) t.Cleanup(func() { - kb.Delete("keyname1", "", false) + kb.Delete("keyname1") }) mockIn.Reset("test1234\n") - key1, err := kb.Get("keyname1") + key1, err := kb.Key("keyname1") require.NoError(t, err) require.NotNil(t, key1) diff --git a/client/keys/add_test.go b/client/keys/add_test.go index 172d7d9e1ce..9ee735d9be2 100644 --- a/client/keys/add_test.go +++ b/client/keys/add_test.go @@ -27,11 +27,11 @@ func Test_runAddCmdBasic(t *testing.T) { viper.Set(cli.OutputFlag, OutputFormatText) mockIn.Reset("y\n") - kb, err := keyring.NewKeyring(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), kbHome, mockIn) + kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), kbHome, mockIn) require.NoError(t, err) t.Cleanup(func() { - kb.Delete("keyname1", "", false) // nolint:errcheck - kb.Delete("keyname2", "", false) // nolint:errcheck + kb.Delete("keyname1") // nolint:errcheck + kb.Delete("keyname2") // nolint:errcheck }) assert.NoError(t, runAddCmd(cmd, []string{"keyname1"})) diff --git a/client/keys/delete.go b/client/keys/delete.go index 0c379e49bca..a6631fa3bfb 100644 --- a/client/keys/delete.go +++ b/client/keys/delete.go @@ -43,13 +43,13 @@ private keys stored in a ledger device cannot be deleted with the CLI. func runDeleteCmd(cmd *cobra.Command, args []string) error { buf := bufio.NewReader(cmd.InOrStdin()) - kb, err := keyring.NewKeyring(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), buf) + kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), buf) if err != nil { return err } for _, name := range args { - info, err := kb.Get(name) + info, err := kb.Key(name) if err != nil { return err } @@ -62,7 +62,7 @@ func runDeleteCmd(cmd *cobra.Command, args []string) error { } } - if err := kb.Delete(name, "", true); err != nil { + if err := kb.Delete(name); err != nil { return err } cmd.PrintErrln("Public key reference deleted") @@ -70,7 +70,7 @@ func runDeleteCmd(cmd *cobra.Command, args []string) error { } // old password and skip flag arguments are ignored - if err := kb.Delete(name, "", true); err != nil { + if err := kb.Delete(name); err != nil { return err } cmd.PrintErrln("Key deleted forever (uh oh!)") diff --git a/client/keys/delete_test.go b/client/keys/delete_test.go index 73db7faecb6..4f6df4131a7 100644 --- a/client/keys/delete_test.go +++ b/client/keys/delete_test.go @@ -25,11 +25,11 @@ func Test_runDeleteCmd(t *testing.T) { fakeKeyName1 := "runDeleteCmd_Key1" fakeKeyName2 := "runDeleteCmd_Key2" - kb, err := keyring.NewKeyring(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn) + kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn) require.NoError(t, err) t.Cleanup(func() { - kb.Delete("runDeleteCmd_Key1", "", false) // nolint:errcheck - kb.Delete("runDeleteCmd_Key2", "", false) // nolint:errcheck + kb.Delete("runDeleteCmd_Key1") // nolint:errcheck + kb.Delete("runDeleteCmd_Key2") // nolint:errcheck }) // Now add a temporary keybase @@ -38,12 +38,13 @@ func Test_runDeleteCmd(t *testing.T) { viper.Set(flags.FlagHome, kbHome) // Now - kb, err = keyring.NewKeyring(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), kbHome, mockIn) + path := sdk.GetConfig().GetFullFundraiserPath() + kb, err = keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), kbHome, mockIn) require.NoError(t, err) - _, err = kb.CreateAccount(fakeKeyName1, tests.TestMnemonic, "", "", "0", keyring.Secp256k1) + _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, keyring.AltSecp256k1) require.NoError(t, err) - _, err = kb.CreateAccount(fakeKeyName2, tests.TestMnemonic, "", "", "1", keyring.Secp256k1) + _, err = kb.NewAccount(fakeKeyName2, tests.TestMnemonic, "", path, keyring.AltSecp256k1) require.NoError(t, err) err = runDeleteCmd(deleteKeyCommand, []string{"blah"}) @@ -56,23 +57,23 @@ func Test_runDeleteCmd(t *testing.T) { require.Equal(t, "EOF", err.Error()) { - _, err = kb.Get(fakeKeyName1) + _, err = kb.Key(fakeKeyName1) require.NoError(t, err) // Now there is a confirmation viper.Set(flagYes, true) require.NoError(t, runDeleteCmd(deleteKeyCommand, []string{fakeKeyName1})) - _, err = kb.Get(fakeKeyName1) + _, err = kb.Key(fakeKeyName1) require.Error(t, err) // Key1 is gone } viper.Set(flagYes, true) - _, err = kb.Get(fakeKeyName2) + _, err = kb.Key(fakeKeyName2) require.NoError(t, err) err = runDeleteCmd(deleteKeyCommand, []string{fakeKeyName2}) require.NoError(t, err) - _, err = kb.Get(fakeKeyName2) + _, err = kb.Key(fakeKeyName2) require.Error(t, err) // Key2 is gone } diff --git a/client/keys/export_test.go b/client/keys/export_test.go index 175acdfe92f..2b83ecd822a 100644 --- a/client/keys/export_test.go +++ b/client/keys/export_test.go @@ -22,13 +22,14 @@ func Test_runExportCmd(t *testing.T) { viper.Set(flags.FlagHome, kbHome) // create a key - kb, err := keyring.NewKeyring(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn) + kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn) require.NoError(t, err) t.Cleanup(func() { - kb.Delete("keyname1", "", false) // nolint:errcheck + kb.Delete("keyname1") // nolint:errcheck }) - _, err = kb.CreateAccount("keyname1", tests.TestMnemonic, "", "123456789", "", keyring.Secp256k1) + path := sdk.GetConfig().GetFullFundraiserPath() + _, err = kb.NewAccount("keyname1", tests.TestMnemonic, "", path, keyring.AltSecp256k1) require.NoError(t, err) // Now enter password diff --git a/client/keys/import_test.go b/client/keys/import_test.go index cad3d6a44d3..fad892cdaa1 100644 --- a/client/keys/import_test.go +++ b/client/keys/import_test.go @@ -23,10 +23,10 @@ func Test_runImportCmd(t *testing.T) { t.Cleanup(cleanUp) viper.Set(flags.FlagHome, kbHome) - kb, err := keyring.NewKeyring(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn) + kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn) require.NoError(t, err) t.Cleanup(func() { - kb.Delete("keyname1", "", false) // nolint:errcheck + kb.Delete("keyname1") // nolint:errcheck }) keyfile := filepath.Join(kbHome, "key.asc") diff --git a/client/keys/list_test.go b/client/keys/list_test.go index d5d4eebcf70..49ecdf5c940 100644 --- a/client/keys/list_test.go +++ b/client/keys/list_test.go @@ -31,14 +31,15 @@ func Test_runListCmd(t *testing.T) { viper.Set(flags.FlagHome, kbHome2) mockIn, _, _ := tests.ApplyMockIO(cmdBasic) - kb, err := keyring.NewKeyring(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn) + kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn) require.NoError(t, err) - _, err = kb.CreateAccount("something", tests.TestMnemonic, "", "", "", keyring.Secp256k1) + path := "" //sdk.GetConfig().GetFullFundraiserPath() + _, err = kb.NewAccount("something", tests.TestMnemonic, "", path, keyring.AltSecp256k1) require.NoError(t, err) t.Cleanup(func() { - kb.Delete("something", "", false) // nolint:errcheck + kb.Delete("something") // nolint:errcheck }) testData := []struct { diff --git a/client/keys/show_test.go b/client/keys/show_test.go index cf157c4c588..4da7057aa90 100644 --- a/client/keys/show_test.go +++ b/client/keys/show_test.go @@ -12,6 +12,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/crypto/keys/hd" "github.com/cosmos/cosmos-sdk/tests" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -48,16 +49,18 @@ func Test_runShowCmd(t *testing.T) { fakeKeyName1 := "runShowCmd_Key1" fakeKeyName2 := "runShowCmd_Key2" - kb, err := keyring.NewKeyring(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn) + kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn) require.NoError(t, err) t.Cleanup(func() { - kb.Delete("runShowCmd_Key1", "", false) - kb.Delete("runShowCmd_Key2", "", false) + kb.Delete("runShowCmd_Key1") + kb.Delete("runShowCmd_Key2") }) - _, err = kb.CreateAccount(fakeKeyName1, tests.TestMnemonic, "", "", "0", keyring.Secp256k1) + + path := hd.NewFundraiserParams(1, sdk.CoinType, 0).String() + _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, keyring.AltSecp256k1) require.NoError(t, err) - _, err = kb.CreateAccount(fakeKeyName2, tests.TestMnemonic, "", "", "1", keyring.Secp256k1) + _, err = kb.NewAccount(fakeKeyName2, tests.TestMnemonic, "", path, keyring.AltSecp256k1) require.NoError(t, err) // Now try single key @@ -69,7 +72,7 @@ func Test_runShowCmd(t *testing.T) { // try fetch by name require.NoError(t, runShowCmd(cmd, []string{fakeKeyName1})) // try fetch by addr - info, err := kb.Get(fakeKeyName1) + info, err := kb.Key(fakeKeyName1) require.NoError(t, err) require.NoError(t, runShowCmd(cmd, []string{info.GetAddress().String()})) diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go index 61574ac7701..8b65dd1d7cf 100644 --- a/crypto/keyring/altkeyring.go +++ b/crypto/keyring/altkeyring.go @@ -1,6 +1,7 @@ package keyring import ( + "encoding/hex" "fmt" "io" "sort" @@ -474,3 +475,7 @@ func (ks keystore) writeMultisigKey(name string, pub tmcrypto.PubKey) (Info, err return info, nil } + +func addrHexKeyAsString(address types.Address) string { + return fmt.Sprintf("%s.%s", hex.EncodeToString(address.Bytes()), addressSuffix) +} diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/altkeyring_test.go index e918cd6c34e..69483ecb4ec 100644 --- a/crypto/keyring/altkeyring_test.go +++ b/crypto/keyring/altkeyring_test.go @@ -1,18 +1,22 @@ package keyring import ( + "bytes" "fmt" + "strings" "testing" + "github.com/cosmos/go-bip39" "github.com/stretchr/testify/require" - "github.com/tendermint/tendermint/crypto" + tmcrypto "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/crypto/multisig" + "github.com/tendermint/tendermint/crypto/secp256k1" - "github.com/cosmos/go-bip39" - + "github.com/cosmos/cosmos-sdk/crypto" + "github.com/cosmos/cosmos-sdk/crypto/keys/hd" "github.com/cosmos/cosmos-sdk/tests" - "github.com/cosmos/cosmos-sdk/types" + sdk "github.com/cosmos/cosmos-sdk/types" ) const ( @@ -21,6 +25,814 @@ const ( otherID = "otherID" ) +func init() { + crypto.BcryptSecurityParameter = 1 +} + +func TestNewKeyring(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + mockIn := strings.NewReader("") + t.Cleanup(cleanup) + kr, err := New("cosmos", BackendFile, dir, mockIn) + require.NoError(t, err) + + mockIn.Reset("password\npassword\n") + info, _, err := kr.NewMnemonic("foo", English, AltSecp256k1) + require.NoError(t, err) + require.Equal(t, "foo", info.GetName()) +} + +func TestKeyManagementKeyRing(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + t.Cleanup(cleanup) + kb, err := New("keybasename", "test", dir, nil) + require.NoError(t, err) + + algo := AltSecp256k1 + n1, n2, n3 := "personal", "business", "other" + + // Check empty state + l, err := kb.List() + require.Nil(t, err) + require.Empty(t, l) + + _, _, err = kb.NewMnemonic(n1, English, notSupportedAlgo{}) + require.Error(t, err, "ed25519 keys are currently not supported by keybase") + + // create some keys + _, err = kb.Key(n1) + require.Error(t, err) + i, _, err := kb.NewMnemonic(n1, English, algo) + + require.NoError(t, err) + require.Equal(t, n1, i.GetName()) + _, _, err = kb.NewMnemonic(n2, English, algo) + require.NoError(t, err) + + // we can get these keys + i2, err := kb.Key(n2) + require.NoError(t, err) + _, err = kb.Key(n3) + require.NotNil(t, err) + _, err = kb.KeyByAddress(accAddr(i2)) + require.NoError(t, err) + addr, err := sdk.AccAddressFromBech32("cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t") + require.NoError(t, err) + _, err = kb.KeyByAddress(addr) + require.NotNil(t, err) + + // list shows them in order + keyS, err := kb.List() + require.NoError(t, err) + require.Equal(t, 2, len(keyS)) + // note these are in alphabetical order + require.Equal(t, n2, keyS[0].GetName()) + require.Equal(t, n1, keyS[1].GetName()) + require.Equal(t, i2.GetPubKey(), keyS[0].GetPubKey()) + + // deleting a key removes it + err = kb.Delete("bad name") + require.NotNil(t, err) + err = kb.Delete(n1) + require.NoError(t, err) + keyS, err = kb.List() + require.NoError(t, err) + require.Equal(t, 1, len(keyS)) + _, err = kb.Key(n1) + require.Error(t, err) + + // create an offline key + o1 := "offline" + priv1 := ed25519.GenPrivKey() + pub1 := priv1.PubKey() + i, err = kb.SavePubKey(o1, pub1, Ed25519) + require.Nil(t, err) + require.Equal(t, pub1, i.GetPubKey()) + require.Equal(t, o1, i.GetName()) + keyS, err = kb.List() + require.NoError(t, err) + require.Equal(t, 2, len(keyS)) + + // delete the offline key + err = kb.Delete(o1) + require.NoError(t, err) + keyS, err = kb.List() + require.NoError(t, err) + require.Equal(t, 1, len(keyS)) + + // addr cache gets nuked - and test skip flag + require.NoError(t, kb.Delete(n2)) +} + +// TestSignVerify does some detailed checks on how we sign and validate +// signatures +func TestSignVerifyKeyRingWithLedger(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + t.Cleanup(cleanup) + kb, err := New("keybasename", "test", dir, nil) + require.NoError(t, err) + + i1, err := kb.SaveLedgerKey("key", AltSecp256k1, "cosmos", 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()) + + d1 := []byte("my first message") + s1, pub1, err := kb.Sign("key", d1) + require.NoError(t, err) + + s2, pub2, err := SignWithLedger(i1, d1) + require.NoError(t, err) + + require.Equal(t, i1.GetPubKey(), pub1) + require.Equal(t, i1.GetPubKey(), pub2) + require.True(t, pub1.VerifyBytes(d1, s1)) + require.True(t, i1.GetPubKey().VerifyBytes(d1, s1)) + require.True(t, bytes.Equal(s1, s2)) + + localInfo, _, err := kb.NewMnemonic("test", English, AltSecp256k1) + require.NoError(t, err) + _, _, err = SignWithLedger(localInfo, d1) + require.Error(t, err) + require.Equal(t, "not a ledger object", err.Error()) +} + +func TestSignVerifyKeyRing(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + t.Cleanup(cleanup) + + kb, err := New("keybasename", "test", dir, nil) + require.NoError(t, err) + algo := AltSecp256k1 + + n1, n2, n3 := "some dude", "a dudette", "dude-ish" + + // create two users and get their info + i1, _, err := kb.NewMnemonic(n1, English, algo) + require.Nil(t, err) + + i2, _, err := kb.NewMnemonic(n2, English, algo) + require.Nil(t, err) + + // Import a public key + armor, err := kb.ExportPubKeyArmor(n2) + require.Nil(t, err) + err = kb.ImportPubKey(n3, armor) + require.NoError(t, err) + i3, err := kb.Key(n3) + require.NoError(t, err) + require.Equal(t, i3.GetName(), n3) + + // let's try to sign some messages + d1 := []byte("my first message") + d2 := []byte("some other important info!") + d3 := []byte("feels like I forgot something...") + + // try signing both data with both .. + s11, pub1, err := kb.Sign(n1, d1) + require.Nil(t, err) + require.Equal(t, i1.GetPubKey(), pub1) + + s12, pub1, err := kb.Sign(n1, d2) + require.Nil(t, err) + require.Equal(t, i1.GetPubKey(), pub1) + + s21, pub2, err := kb.Sign(n2, d1) + require.Nil(t, err) + require.Equal(t, i2.GetPubKey(), pub2) + + s22, pub2, err := kb.Sign(n2, d2) + require.Nil(t, err) + require.Equal(t, i2.GetPubKey(), pub2) + + // let's try to validate and make sure it only works when everything is proper + cases := []struct { + key tmcrypto.PubKey + data []byte + sig []byte + valid bool + }{ + // proper matches + {i1.GetPubKey(), d1, s11, true}, + // change data, pubkey, or signature leads to fail + {i1.GetPubKey(), d2, s11, false}, + {i2.GetPubKey(), d1, s11, false}, + {i1.GetPubKey(), d1, s21, false}, + // make sure other successes + {i1.GetPubKey(), d2, s12, true}, + {i2.GetPubKey(), d1, s21, true}, + {i2.GetPubKey(), d2, s22, true}, + } + + for i, tc := range cases { + valid := tc.key.VerifyBytes(tc.data, tc.sig) + require.Equal(t, tc.valid, valid, "%d", i) + } + + // Now try to sign data with a secret-less key + _, _, err = kb.Sign(n3, d3) + require.Error(t, err) + require.Equal(t, "cannot sign with offline keys", err.Error()) +} + +func TestExportImportKeyRing(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + t.Cleanup(cleanup) + kb, err := New("keybasename", "test", dir, nil) + require.NoError(t, err) + + info, _, err := kb.NewMnemonic("john", English, AltSecp256k1) + require.NoError(t, err) + require.Equal(t, info.GetName(), "john") + + john, err := kb.Key("john") + require.NoError(t, err) + require.Equal(t, info.GetName(), "john") + johnAddr := info.GetPubKey().Address() + + armor, err := kb.ExportPrivKeyArmor("john", "apassphrase") + require.NoError(t, err) + + err = kb.ImportPrivKey("john2", armor, "apassphrase") + require.NoError(t, err) + + john2, err := kb.Key("john2") + require.NoError(t, err) + + require.Equal(t, john.GetPubKey().Address(), johnAddr) + require.Equal(t, john.GetName(), "john") + require.Equal(t, john.GetAddress(), john2.GetAddress()) + require.Equal(t, john.GetAlgo(), john2.GetAlgo()) + require.Equal(t, john.GetPubKey(), john2.GetPubKey()) + require.Equal(t, john.GetType(), john2.GetType()) +} + +func TestExportImportPubKeyKeyRing(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + t.Cleanup(cleanup) + kb, err := New("keybasename", "test", dir, nil) + require.NoError(t, err) + algo := AltSecp256k1 + + // CreateMnemonic a private-public key pair and ensure consistency + info, _, err := kb.NewMnemonic("john", English, algo) + require.Nil(t, err) + require.NotEqual(t, info, "") + require.Equal(t, info.GetName(), "john") + addr := info.GetPubKey().Address() + john, err := kb.Key("john") + require.NoError(t, err) + require.Equal(t, john.GetName(), "john") + require.Equal(t, john.GetPubKey().Address(), addr) + + // Export the public key only + armor, err := kb.ExportPubKeyArmor("john") + require.NoError(t, err) + // Import it under a different name + err = kb.ImportPubKey("john-pubkey-only", armor) + require.NoError(t, err) + // Ensure consistency + john2, err := kb.Key("john-pubkey-only") + require.NoError(t, err) + // Compare the public keys + require.True(t, john.GetPubKey().Equals(john2.GetPubKey())) + // Ensure the original key hasn't changed + john, err = kb.Key("john") + require.NoError(t, err) + require.Equal(t, john.GetPubKey().Address(), addr) + require.Equal(t, john.GetName(), "john") + + // Ensure keys cannot be overwritten + err = kb.ImportPubKey("john-pubkey-only", armor) + require.NotNil(t, err) +} + +func TestAdvancedKeyManagementKeyRing(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + t.Cleanup(cleanup) + kb, err := New("keybasename", "test", dir, nil) + require.NoError(t, err) + + algo := AltSecp256k1 + n1, n2 := "old-name", "new name" + + // make sure key works with initial password + _, _, err = kb.NewMnemonic(n1, English, algo) + require.Nil(t, err, "%+v", err) + + _, err = kb.ExportPubKeyArmor(n1 + ".notreal") + require.NotNil(t, err) + _, err = kb.ExportPubKeyArmor(" " + n1) + require.NotNil(t, err) + _, err = kb.ExportPubKeyArmor(n1 + " ") + require.NotNil(t, err) + _, err = kb.ExportPubKeyArmor("") + require.NotNil(t, err) + exported, err := kb.ExportPubKeyArmor(n1) + require.Nil(t, err, "%+v", err) + + // import succeeds + err = kb.ImportPubKey(n2, exported) + require.NoError(t, err) + + // second import fails + err = kb.ImportPubKey(n2, exported) + require.NotNil(t, err) +} + +func TestSeedPhraseKeyRing(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + t.Cleanup(cleanup) + kb, err := New("keybasename", "test", dir, nil) + require.NoError(t, err) + + algo := AltSecp256k1 + n1, n2 := "lost-key", "found-again" + + // make sure key works with initial password + info, mnemonic, err := kb.NewMnemonic(n1, English, algo) + require.Nil(t, err, "%+v", err) + require.Equal(t, n1, info.GetName()) + require.NotEmpty(t, mnemonic) + + // now, let us delete this key + err = kb.Delete(n1) + require.Nil(t, err, "%+v", err) + _, err = kb.Key(n1) + require.NotNil(t, err) + + // let us re-create it from the mnemonic-phrase + params := *hd.NewFundraiserParams(0, sdk.CoinType, 0) + hdPath := params.String() + newInfo, err := kb.NewAccount(n2, mnemonic, DefaultBIP39Passphrase, hdPath, AltSecp256k1) + require.NoError(t, err) + require.Equal(t, n2, newInfo.GetName()) + require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) + require.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) +} + +func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + t.Cleanup(cleanup) + kb, err := New("keybasename", "test", dir, nil) + require.NoError(t, err) + + _, _, err = kb.NewMnemonic("john", English, AltSecp256k1) + require.NoError(t, err) + + keystr, err := kb.ExportPrivKeyArmor("john", "somepassword") + require.NoError(t, err) + require.NotEmpty(t, keystr) + + // try import the key - wrong password + err = kb.ImportPrivKey("john2", keystr, "bad pass") + require.Equal(t, "failed to decrypt private key: ciphertext decryption failed", err.Error()) + + // try import the key with the correct password + require.NoError(t, kb.ImportPrivKey("john2", keystr, "somepassword")) + + // overwrite is not allowed + err = kb.ImportPrivKey("john2", keystr, "password") + require.Equal(t, "cannot overwrite key: john2", err.Error()) + + // try export non existing key + _, err = kb.ExportPrivKeyArmor("john3", "wrongpassword") + require.Equal(t, "The specified item could not be found in the keyring", err.Error()) +} + +func TestInMemoryLanguage(t *testing.T) { + kb := NewInMemory() + _, _, err := kb.NewMnemonic("something", Japanese, AltSecp256k1) + require.Error(t, err) + require.Equal(t, "unsupported language: only english is supported", err.Error()) +} + +func TestInMemoryCreateMultisig(t *testing.T) { + kb, err := New("keybasename", "memory", "", nil) + require.NoError(t, err) + multi := multisig.PubKeyMultisigThreshold{ + K: 1, + PubKeys: []tmcrypto.PubKey{secp256k1.GenPrivKey().PubKey()}, + } + _, err = kb.SaveMultisig("multi", multi) + require.NoError(t, err) +} + +func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { + kb := NewInMemory() + _, err := kb.NewAccount( + "some_account", + "malarkey pair crucial catch public canyon evil outer stage ten gym tornado", + "", CreateHDPath(0, 0).String(), AltSecp256k1) + require.Error(t, err) + require.Equal(t, "Invalid mnemonic", err.Error()) +} + +func TestInMemoryCreateLedger(t *testing.T) { + kb := NewInMemory() + + ledger, err := kb.SaveLedgerKey("some_account", AltSecp256k1, "cosmos", 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) + 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() + pk, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) + require.NoError(t, err) + require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) + + // Check that restoring the key gets the same results + restoredKey, err := kb.Key("some_account") + require.NoError(t, err) + require.NotNil(t, restoredKey) + require.Equal(t, "some_account", restoredKey.GetName()) + require.Equal(t, TypeLedger, restoredKey.GetType()) + pubKey = restoredKey.GetPubKey() + pk, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) + require.NoError(t, err) + require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) + + path, err := restoredKey.GetPath() + require.NoError(t, err) + require.Equal(t, "44'/118'/3'/0/1", path.String()) +} + +// TestInMemoryKeyManagement makes sure we can manipulate these keys well +func TestInMemoryKeyManagement(t *testing.T) { + // make the storage with reasonable defaults + cstore := NewInMemory() + + algo := AltSecp256k1 + n1, n2, n3 := "personal", "business", "other" + + // Check empty state + l, err := cstore.List() + require.Nil(t, err) + require.Empty(t, l) + + _, _, err = cstore.NewMnemonic(n1, English, notSupportedAlgo{}) + require.Error(t, err, "ed25519 keys are currently not supported by keybase") + + // create some keys + _, err = cstore.Key(n1) + require.Error(t, err) + i, _, err := cstore.NewMnemonic(n1, English, algo) + + require.NoError(t, err) + require.Equal(t, n1, i.GetName()) + _, _, err = cstore.NewMnemonic(n2, English, algo) + require.NoError(t, err) + + // we can get these keys + i2, err := cstore.Key(n2) + require.NoError(t, err) + _, err = cstore.Key(n3) + require.NotNil(t, err) + _, err = cstore.KeyByAddress(accAddr(i2)) + require.NoError(t, err) + addr, err := sdk.AccAddressFromBech32("cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t") + require.NoError(t, err) + _, err = cstore.KeyByAddress(addr) + require.NotNil(t, err) + + // list shows them in order + keyS, err := cstore.List() + require.NoError(t, err) + require.Equal(t, 2, len(keyS)) + // note these are in alphabetical order + require.Equal(t, n2, keyS[0].GetName()) + require.Equal(t, n1, keyS[1].GetName()) + require.Equal(t, i2.GetPubKey(), keyS[0].GetPubKey()) + + // deleting a key removes it + err = cstore.Delete("bad name") + require.NotNil(t, err) + err = cstore.Delete(n1) + require.NoError(t, err) + keyS, err = cstore.List() + require.NoError(t, err) + require.Equal(t, 1, len(keyS)) + _, err = cstore.Key(n1) + require.Error(t, err) + + // create an offline key + o1 := "offline" + priv1 := ed25519.GenPrivKey() + pub1 := priv1.PubKey() + i, err = cstore.SavePubKey(o1, pub1, Ed25519) + require.Nil(t, err) + require.Equal(t, pub1, i.GetPubKey()) + require.Equal(t, o1, i.GetName()) + iOffline := i.(*offlineInfo) + require.Equal(t, Ed25519, iOffline.GetAlgo()) + keyS, err = cstore.List() + require.NoError(t, err) + require.Equal(t, 2, len(keyS)) + + // delete the offline key + err = cstore.Delete(o1) + require.NoError(t, err) + keyS, err = cstore.List() + require.NoError(t, err) + require.Equal(t, 1, len(keyS)) + + // addr cache gets nuked - and test skip flag + err = cstore.Delete(n2) + require.NoError(t, err) +} + +// TestInMemorySignVerify does some detailed checks on how we sign and validate +// signatures +func TestInMemorySignVerify(t *testing.T) { + cstore := NewInMemory() + algo := AltSecp256k1 + + n1, n2, n3 := "some dude", "a dudette", "dude-ish" + + // create two users and get their info + i1, _, err := cstore.NewMnemonic(n1, English, algo) + require.Nil(t, err) + + i2, _, err := cstore.NewMnemonic(n2, English, algo) + require.Nil(t, err) + + // Import a public key + armor, err := cstore.ExportPubKeyArmor(n2) + require.Nil(t, err) + err = cstore.ImportPubKey(n3, armor) + require.NoError(t, err) + i3, err := cstore.Key(n3) + require.NoError(t, err) + require.Equal(t, i3.GetName(), n3) + + // let's try to sign some messages + d1 := []byte("my first message") + d2 := []byte("some other important info!") + d3 := []byte("feels like I forgot something...") + + // try signing both data with both .. + s11, pub1, err := cstore.Sign(n1, d1) + require.Nil(t, err) + require.Equal(t, i1.GetPubKey(), pub1) + + s12, pub1, err := cstore.Sign(n1, d2) + require.Nil(t, err) + require.Equal(t, i1.GetPubKey(), pub1) + + s21, pub2, err := cstore.Sign(n2, d1) + require.Nil(t, err) + require.Equal(t, i2.GetPubKey(), pub2) + + s22, pub2, err := cstore.Sign(n2, d2) + require.Nil(t, err) + require.Equal(t, i2.GetPubKey(), pub2) + + // let's try to validate and make sure it only works when everything is proper + cases := []struct { + key tmcrypto.PubKey + data []byte + sig []byte + valid bool + }{ + // proper matches + {i1.GetPubKey(), d1, s11, true}, + // change data, pubkey, or signature leads to fail + {i1.GetPubKey(), d2, s11, false}, + {i2.GetPubKey(), d1, s11, false}, + {i1.GetPubKey(), d1, s21, false}, + // make sure other successes + {i1.GetPubKey(), d2, s12, true}, + {i2.GetPubKey(), d1, s21, true}, + {i2.GetPubKey(), d2, s22, true}, + } + + for i, tc := range cases { + valid := tc.key.VerifyBytes(tc.data, tc.sig) + require.Equal(t, tc.valid, valid, "%d", i) + } + + // Now try to sign data with a secret-less key + _, _, err = cstore.Sign(n3, d3) + require.Error(t, err) + require.Equal(t, "cannot sign with offline keys", err.Error()) +} + +// TestInMemoryExportImport tests exporting and importing +func TestInMemoryExportImport(t *testing.T) { + // make the storage with reasonable defaults + cstore := NewInMemory() + + info, _, err := cstore.NewMnemonic("john", English, AltSecp256k1) + require.NoError(t, err) + require.Equal(t, info.GetName(), "john") + + john, err := cstore.Key("john") + require.NoError(t, err) + require.Equal(t, info.GetName(), "john") + johnAddr := info.GetPubKey().Address() + + armor, err := cstore.ExportPubKeyArmor("john") + require.NoError(t, err) + + err = cstore.ImportPubKey("john2", armor) + require.NoError(t, err) + + john2, err := cstore.Key("john2") + require.NoError(t, err) + + require.Equal(t, john.GetPubKey().Address(), johnAddr) + require.Equal(t, john.GetName(), "john") + require.Equal(t, john.GetAddress(), john2.GetAddress()) + require.Equal(t, john.GetAlgo(), john2.GetAlgo()) + require.Equal(t, john.GetPubKey(), john2.GetPubKey()) +} + +func TestInMemoryExportImportPrivKey(t *testing.T) { + kb := NewInMemory() + + info, _, err := kb.NewMnemonic("john", English, AltSecp256k1) + require.NoError(t, err) + require.Equal(t, info.GetName(), "john") + priv1, err := kb.Key("john") + require.NoError(t, err) + + armored, err := kb.ExportPrivKeyArmor("john", "secretcpw") + require.NoError(t, err) + + // delete exported key + require.NoError(t, kb.Delete("john")) + _, err = kb.Key("john") + require.Error(t, err) + + // import armored key + require.NoError(t, kb.ImportPrivKey("john", armored, "secretcpw")) + + // ensure old and new keys match + priv2, err := kb.Key("john") + require.NoError(t, err) + require.True(t, priv1.GetPubKey().Equals(priv2.GetPubKey())) +} + +func TestInMemoryExportImportPubKey(t *testing.T) { + // make the storage with reasonable defaults + cstore := NewInMemory() + + // CreateMnemonic a private-public key pair and ensure consistency + info, _, err := cstore.NewMnemonic("john", English, AltSecp256k1) + require.Nil(t, err) + require.NotEqual(t, info, "") + require.Equal(t, info.GetName(), "john") + addr := info.GetPubKey().Address() + john, err := cstore.Key("john") + require.NoError(t, err) + require.Equal(t, john.GetName(), "john") + require.Equal(t, john.GetPubKey().Address(), addr) + + // Export the public key only + armor, err := cstore.ExportPubKeyArmor("john") + require.NoError(t, err) + // Import it under a different name + err = cstore.ImportPubKey("john-pubkey-only", armor) + require.NoError(t, err) + // Ensure consistency + john2, err := cstore.Key("john-pubkey-only") + require.NoError(t, err) + // Compare the public keys + require.True(t, john.GetPubKey().Equals(john2.GetPubKey())) + // Ensure the original key hasn't changed + john, err = cstore.Key("john") + require.NoError(t, err) + require.Equal(t, john.GetPubKey().Address(), addr) + require.Equal(t, john.GetName(), "john") + + // Ensure keys cannot be overwritten + err = cstore.ImportPubKey("john-pubkey-only", armor) + require.NotNil(t, err) +} + +// TestInMemoryAdvancedKeyManagement verifies update, import, export functionality +func TestInMemoryAdvancedKeyManagement(t *testing.T) { + // make the storage with reasonable defaults + cstore := NewInMemory() + + algo := AltSecp256k1 + n1, n2 := "old-name", "new name" + + // make sure key works with initial password + _, _, err := cstore.NewMnemonic(n1, English, algo) + require.Nil(t, err, "%+v", err) + + // exporting requires the proper name and passphrase + _, err = cstore.ExportPubKeyArmor(n1 + ".notreal") + require.NotNil(t, err) + _, err = cstore.ExportPubKeyArmor(" " + n1) + require.NotNil(t, err) + _, err = cstore.ExportPubKeyArmor(n1 + " ") + require.NotNil(t, err) + _, err = cstore.ExportPubKeyArmor("") + require.NotNil(t, err) + exported, err := cstore.ExportPubKeyArmor(n1) + require.Nil(t, err, "%+v", err) + + // import succeeds + err = cstore.ImportPubKey(n2, exported) + require.NoError(t, err) + + // second import fails + err = cstore.ImportPubKey(n2, exported) + require.NotNil(t, err) +} + +// TestInMemorySeedPhrase verifies restoring from a seed phrase +func TestInMemorySeedPhrase(t *testing.T) { + + // make the storage with reasonable defaults + cstore := NewInMemory() + + algo := AltSecp256k1 + n1, n2 := "lost-key", "found-again" + + // make sure key works with initial password + info, mnemonic, err := cstore.NewMnemonic(n1, English, algo) + require.Nil(t, err, "%+v", err) + require.Equal(t, n1, info.GetName()) + require.NotEmpty(t, mnemonic) + + // now, let us delete this key + err = cstore.Delete(n1) + require.Nil(t, err, "%+v", err) + _, err = cstore.Key(n1) + require.NotNil(t, err) + + // let us re-create it from the mnemonic-phrase + params := *hd.NewFundraiserParams(0, sdk.CoinType, 0) + hdPath := params.String() + newInfo, err := cstore.NewAccount(n2, mnemonic, DefaultBIP39Passphrase, hdPath, algo) + require.NoError(t, err) + require.Equal(t, n2, newInfo.GetName()) + require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) + require.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) +} + +func ExampleNew() { + // Select the encryption and storage for your cryptostore + cstore := NewInMemory() + + sec := AltSecp256k1 + + // Add keys and see they return in alphabetical order + bob, _, err := cstore.NewMnemonic("Bob", English, sec) + if err != nil { + // this should never happen + fmt.Println(err) + } else { + // return info here just like in List + fmt.Println(bob.GetName()) + } + _, _, _ = cstore.NewMnemonic("Alice", English, sec) + _, _, _ = cstore.NewMnemonic("Carl", English, sec) + info, _ := cstore.List() + for _, i := range info { + fmt.Println(i.GetName()) + } + + // We need to use passphrase to generate a signature + tx := []byte("deadbeef") + sig, pub, err := cstore.Sign("Bob", tx) + if err != nil { + fmt.Println("don't accept real passphrase") + } + + // and we can validate the signature with publicly available info + binfo, _ := cstore.Key("Bob") + if !binfo.GetPubKey().Equals(bob.GetPubKey()) { + fmt.Println("Get and Create return different keys") + } + + if pub.Equals(binfo.GetPubKey()) { + fmt.Println("signed by Bob") + } + if !pub.VerifyBytes(tx, sig) { + fmt.Println("invalid signature") + } + + // Output: + // Bob + // Alice + // Bob + // Carl + // signed by Bob +} + func TestAltKeyring_List(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) @@ -71,10 +883,10 @@ func TestAltKeyring_NewAccount(t *testing.T) { uid := "newUid" // Fails on creating unsupported pubKeyType - _, err = keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), notSupportedAlgo{}) + _, err = keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.GetConfig().GetFullFundraiserPath(), notSupportedAlgo{}) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) - info, err := keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), AltSecp256k1) + info, err := keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.GetConfig().GetFullFundraiserPath(), AltSecp256k1) require.NoError(t, err) require.Equal(t, uid, info.GetName()) @@ -104,7 +916,7 @@ 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() - pk, err := types.Bech32ifyPubKey(types.Bech32PubKeyTypeAccPub, pubKey) + pk, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) require.NoError(t, err) require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) @@ -115,7 +927,7 @@ func TestAltKeyring_SaveLedgerKey(t *testing.T) { require.Equal(t, "some_account", restoredKey.GetName()) require.Equal(t, TypeLedger, restoredKey.GetType()) pubKey = restoredKey.GetPubKey() - pk, err = types.Bech32ifyPubKey(types.Bech32PubKeyTypeAccPub, pubKey) + pk, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) require.NoError(t, err) require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) @@ -241,7 +1053,7 @@ func TestAltKeyring_SaveMultisig(t *testing.T) { require.NoError(t, err) key := "multi" - pub := multisig.NewPubKeyMultisigThreshold(2, []crypto.PubKey{mnemonic1.GetPubKey(), mnemonic2.GetPubKey()}) + pub := multisig.NewPubKeyMultisigThreshold(2, []tmcrypto.PubKey{mnemonic1.GetPubKey(), mnemonic2.GetPubKey()}) info, err := keyring.SaveMultisig(key, pub) require.Nil(t, err) @@ -431,3 +1243,7 @@ func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetAlgo(), mnemonic.GetAlgo()) require.Equal(t, key.GetType(), mnemonic.GetType()) } + +func accAddr(info Info) sdk.AccAddress { + return sdk.AccAddress(info.GetAddress()) +} diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 51851955596..55835fe2ac7 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -2,7 +2,6 @@ package keyring import ( "bufio" - "encoding/hex" "fmt" "io" "io/ioutil" @@ -39,8 +38,6 @@ const ( passKeyringPrefix = keyringDirNameFmt ) -var _ Keybase = keyringKeybase{} - // Keyring exposes operations over a backend supported by github.com/99designs/keyring. type Keyring interface { // List all keys. @@ -654,7 +651,3 @@ func newRealPrompt(dir string, buf io.Reader) func(string) (string, error) { func addrHexKey(address types.Address) []byte { return []byte(addrHexKeyAsString(address)) } - -func addrHexKeyAsString(address types.Address) string { - return fmt.Sprintf("%s.%s", hex.EncodeToString(address.Bytes()), addressSuffix) -} diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go deleted file mode 100644 index ab88c7e7821..00000000000 --- a/crypto/keyring/keyring_test.go +++ /dev/null @@ -1,839 +0,0 @@ -package keyring - -import ( - "bytes" - "fmt" - "strings" - "testing" - - "github.com/tendermint/tendermint/crypto/multisig" - "github.com/tendermint/tendermint/crypto/secp256k1" - - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" - tmcrypto "github.com/tendermint/tendermint/crypto" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/tendermint/tendermint/crypto/ed25519" - - "github.com/cosmos/cosmos-sdk/crypto" - "github.com/cosmos/cosmos-sdk/tests" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -func init() { - crypto.BcryptSecurityParameter = 1 -} - -const ( - nums = "1234" - foobar = "foobar" -) - -func TestNewKeyring(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - mockIn := strings.NewReader("") - t.Cleanup(cleanup) - kr, err := New("cosmos", BackendFile, dir, mockIn) - require.NoError(t, err) - - mockIn.Reset("password\npassword\n") - info, _, err := kr.NewMnemonic("foo", English, AltSecp256k1) - require.NoError(t, err) - require.Equal(t, "foo", info.GetName()) -} - -func TestKeyManagementKeyRing(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - kb, err := New("keybasename", "test", dir, nil) - require.NoError(t, err) - - algo := AltSecp256k1 - n1, n2, n3 := "personal", "business", "other" - - // Check empty state - l, err := kb.List() - require.Nil(t, err) - assert.Empty(t, l) - - _, _, err = kb.NewMnemonic(n1, English, notSupportedAlgo{}) - require.Error(t, err, "ed25519 keys are currently not supported by keybase") - - // create some keys - _, err = kb.Key(n1) - require.Error(t, err) - i, _, err := kb.NewMnemonic(n1, English, algo) - - require.NoError(t, err) - require.Equal(t, n1, i.GetName()) - _, _, err = kb.NewMnemonic(n2, English, algo) - require.NoError(t, err) - - // we can get these keys - i2, err := kb.Key(n2) - require.NoError(t, err) - _, err = kb.Key(n3) - require.NotNil(t, err) - _, err = kb.KeyByAddress(accAddr(i2)) - require.NoError(t, err) - addr, err := sdk.AccAddressFromBech32("cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t") - require.NoError(t, err) - _, err = kb.KeyByAddress(addr) - require.NotNil(t, err) - - // list shows them in order - keyS, err := kb.List() - require.NoError(t, err) - require.Equal(t, 2, len(keyS)) - // note these are in alphabetical order - require.Equal(t, n2, keyS[0].GetName()) - require.Equal(t, n1, keyS[1].GetName()) - require.Equal(t, i2.GetPubKey(), keyS[0].GetPubKey()) - - // deleting a key removes it - err = kb.Delete("bad name") - require.NotNil(t, err) - err = kb.Delete(n1) - require.NoError(t, err) - keyS, err = kb.List() - require.NoError(t, err) - require.Equal(t, 1, len(keyS)) - _, err = kb.Key(n1) - require.Error(t, err) - - // create an offline key - o1 := "offline" - priv1 := ed25519.GenPrivKey() - pub1 := priv1.PubKey() - i, err = kb.SavePubKey(o1, pub1, Ed25519) - require.Nil(t, err) - require.Equal(t, pub1, i.GetPubKey()) - require.Equal(t, o1, i.GetName()) - keyS, err = kb.List() - require.NoError(t, err) - require.Equal(t, 2, len(keyS)) - - // delete the offline key - err = kb.Delete(o1) - require.NoError(t, err) - keyS, err = kb.List() - require.NoError(t, err) - require.Equal(t, 1, len(keyS)) - - // addr cache gets nuked - and test skip flag - require.NoError(t, kb.Delete(n2)) -} - -// TestSignVerify does some detailed checks on how we sign and validate -// signatures -func TestSignVerifyKeyRingWithLedger(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - kb, err := New("keybasename", "test", dir, nil) - require.NoError(t, err) - - i1, err := kb.SaveLedgerKey("key", AltSecp256k1, "cosmos", 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()) - - d1 := []byte("my first message") - s1, pub1, err := kb.Sign("key", d1) - require.NoError(t, err) - - s2, pub2, err := SignWithLedger(i1, d1) - require.NoError(t, err) - - require.Equal(t, i1.GetPubKey(), pub1) - require.Equal(t, i1.GetPubKey(), pub2) - require.True(t, pub1.VerifyBytes(d1, s1)) - require.True(t, i1.GetPubKey().VerifyBytes(d1, s1)) - require.True(t, bytes.Equal(s1, s2)) - - localInfo, _, err := kb.NewMnemonic("test", English, AltSecp256k1) - require.NoError(t, err) - _, _, err = SignWithLedger(localInfo, d1) - require.Error(t, err) - require.Equal(t, "not a ledger object", err.Error()) -} - -func TestSignVerifyKeyRing(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - - kb, err := New("keybasename", "test", dir, nil) - require.NoError(t, err) - algo := AltSecp256k1 - - n1, n2, n3 := "some dude", "a dudette", "dude-ish" - - // create two users and get their info - i1, _, err := kb.NewMnemonic(n1, English, algo) - require.Nil(t, err) - - i2, _, err := kb.NewMnemonic(n2, English, algo) - require.Nil(t, err) - - // Import a public key - armor, err := kb.ExportPubKeyArmor(n2) - require.Nil(t, err) - err = kb.ImportPubKey(n3, armor) - require.NoError(t, err) - i3, err := kb.Key(n3) - require.NoError(t, err) - require.Equal(t, i3.GetName(), n3) - - // let's try to sign some messages - d1 := []byte("my first message") - d2 := []byte("some other important info!") - d3 := []byte("feels like I forgot something...") - - // try signing both data with both .. - s11, pub1, err := kb.Sign(n1, d1) - require.Nil(t, err) - require.Equal(t, i1.GetPubKey(), pub1) - - s12, pub1, err := kb.Sign(n1, d2) - require.Nil(t, err) - require.Equal(t, i1.GetPubKey(), pub1) - - s21, pub2, err := kb.Sign(n2, d1) - require.Nil(t, err) - require.Equal(t, i2.GetPubKey(), pub2) - - s22, pub2, err := kb.Sign(n2, d2) - require.Nil(t, err) - require.Equal(t, i2.GetPubKey(), pub2) - - // let's try to validate and make sure it only works when everything is proper - cases := []struct { - key tmcrypto.PubKey - data []byte - sig []byte - valid bool - }{ - // proper matches - {i1.GetPubKey(), d1, s11, true}, - // change data, pubkey, or signature leads to fail - {i1.GetPubKey(), d2, s11, false}, - {i2.GetPubKey(), d1, s11, false}, - {i1.GetPubKey(), d1, s21, false}, - // make sure other successes - {i1.GetPubKey(), d2, s12, true}, - {i2.GetPubKey(), d1, s21, true}, - {i2.GetPubKey(), d2, s22, true}, - } - - for i, tc := range cases { - valid := tc.key.VerifyBytes(tc.data, tc.sig) - require.Equal(t, tc.valid, valid, "%d", i) - } - - // Now try to sign data with a secret-less key - _, _, err = kb.Sign(n3, d3) - require.Error(t, err) - require.Equal(t, "cannot sign with offline keys", err.Error()) -} - -func TestExportImportKeyRing(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - kb, err := New("keybasename", "test", dir, nil) - require.NoError(t, err) - - info, _, err := kb.NewMnemonic("john", English, AltSecp256k1) - require.NoError(t, err) - require.Equal(t, info.GetName(), "john") - - john, err := kb.Key("john") - require.NoError(t, err) - require.Equal(t, info.GetName(), "john") - johnAddr := info.GetPubKey().Address() - - armor, err := kb.ExportPrivKeyArmor("john", "apassphrase") - require.NoError(t, err) - - err = kb.ImportPrivKey("john2", armor, "apassphrase") - require.NoError(t, err) - - john2, err := kb.Key("john2") - require.NoError(t, err) - - require.Equal(t, john.GetPubKey().Address(), johnAddr) - require.Equal(t, john.GetName(), "john") - require.Equal(t, john.GetAddress(), john2.GetAddress()) - require.Equal(t, john.GetAlgo(), john2.GetAlgo()) - require.Equal(t, john.GetPubKey(), john2.GetPubKey()) - require.Equal(t, john.GetType(), john2.GetType()) -} - -func TestExportImportPubKeyKeyRing(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - kb, err := New("keybasename", "test", dir, nil) - require.NoError(t, err) - algo := AltSecp256k1 - - // CreateMnemonic a private-public key pair and ensure consistency - info, _, err := kb.NewMnemonic("john", English, algo) - require.Nil(t, err) - require.NotEqual(t, info, "") - require.Equal(t, info.GetName(), "john") - addr := info.GetPubKey().Address() - john, err := kb.Key("john") - require.NoError(t, err) - require.Equal(t, john.GetName(), "john") - require.Equal(t, john.GetPubKey().Address(), addr) - - // Export the public key only - armor, err := kb.ExportPubKeyArmor("john") - require.NoError(t, err) - // Import it under a different name - err = kb.ImportPubKey("john-pubkey-only", armor) - require.NoError(t, err) - // Ensure consistency - john2, err := kb.Key("john-pubkey-only") - require.NoError(t, err) - // Compare the public keys - require.True(t, john.GetPubKey().Equals(john2.GetPubKey())) - // Ensure the original key hasn't changed - john, err = kb.Key("john") - require.NoError(t, err) - require.Equal(t, john.GetPubKey().Address(), addr) - require.Equal(t, john.GetName(), "john") - - // Ensure keys cannot be overwritten - err = kb.ImportPubKey("john-pubkey-only", armor) - require.NotNil(t, err) -} - -func TestAdvancedKeyManagementKeyRing(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - kb, err := New("keybasename", "test", dir, nil) - require.NoError(t, err) - - algo := AltSecp256k1 - n1, n2 := "old-name", "new name" - - // make sure key works with initial password - _, _, err = kb.NewMnemonic(n1, English, algo) - require.Nil(t, err, "%+v", err) - - _, err = kb.ExportPubKeyArmor(n1 + ".notreal") - require.NotNil(t, err) - _, err = kb.ExportPubKeyArmor(" " + n1) - require.NotNil(t, err) - _, err = kb.ExportPubKeyArmor(n1 + " ") - require.NotNil(t, err) - _, err = kb.ExportPubKeyArmor("") - require.NotNil(t, err) - exported, err := kb.ExportPubKeyArmor(n1) - require.Nil(t, err, "%+v", err) - - // import succeeds - err = kb.ImportPubKey(n2, exported) - require.NoError(t, err) - - // second import fails - err = kb.ImportPubKey(n2, exported) - require.NotNil(t, err) -} - -func TestSeedPhraseKeyRing(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - kb, err := New("keybasename", "test", dir, nil) - require.NoError(t, err) - - algo := AltSecp256k1 - n1, n2 := "lost-key", "found-again" - - // make sure key works with initial password - info, mnemonic, err := kb.NewMnemonic(n1, English, algo) - require.Nil(t, err, "%+v", err) - require.Equal(t, n1, info.GetName()) - assert.NotEmpty(t, mnemonic) - - // now, let us delete this key - err = kb.Delete(n1) - require.Nil(t, err, "%+v", err) - _, err = kb.Key(n1) - require.NotNil(t, err) - - // let us re-create it from the mnemonic-phrase - params := *hd.NewFundraiserParams(0, sdk.CoinType, 0) - hdPath := params.String() - newInfo, err := kb.NewAccount(n2, mnemonic, DefaultBIP39Passphrase, hdPath, AltSecp256k1) - require.NoError(t, err) - require.Equal(t, n2, newInfo.GetName()) - require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) - require.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) -} - -func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - kb, err := New("keybasename", "test", dir, nil) - require.NoError(t, err) - - _, _, err = kb.NewMnemonic("john", English, AltSecp256k1) - require.NoError(t, err) - - keystr, err := kb.ExportPrivKeyArmor("john", "somepassword") - require.NoError(t, err) - require.NotEmpty(t, keystr) - - // try import the key - wrong password - err = kb.ImportPrivKey("john2", keystr, "bad pass") - require.Equal(t, "failed to decrypt private key: ciphertext decryption failed", err.Error()) - - // try import the key with the correct password - require.NoError(t, kb.ImportPrivKey("john2", keystr, "somepassword")) - - // overwrite is not allowed - err = kb.ImportPrivKey("john2", keystr, "password") - require.Equal(t, "cannot overwrite key: john2", err.Error()) - - // try export non existing key - _, err = kb.ExportPrivKeyArmor("john3", "wrongpassword") - require.Equal(t, "The specified item could not be found in the keyring", err.Error()) -} - -func TestInMemoryLanguage(t *testing.T) { - kb := NewInMemory() - _, _, err := kb.NewMnemonic("something", Japanese, AltSecp256k1) - require.Error(t, err) - require.Equal(t, "unsupported language: only english is supported", err.Error()) -} - -func TestInMemoryCreateMultisig(t *testing.T) { - kb, err := New("keybasename", "memory", "", nil) - require.NoError(t, err) - multi := multisig.PubKeyMultisigThreshold{ - K: 1, - PubKeys: []tmcrypto.PubKey{secp256k1.GenPrivKey().PubKey()}, - } - _, err = kb.SaveMultisig("multi", multi) - require.NoError(t, err) -} - -func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { - kb := NewInMemory() - _, err := kb.NewAccount( - "some_account", - "malarkey pair crucial catch public canyon evil outer stage ten gym tornado", - "", CreateHDPath(0, 0).String(), AltSecp256k1) - require.Error(t, err) - require.Equal(t, "Invalid mnemonic", err.Error()) -} - -func TestInMemoryCreateLedger(t *testing.T) { - kb := NewInMemory() - - ledger, err := kb.SaveLedgerKey("some_account", AltSecp256k1, "cosmos", 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) - 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() - pk, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) - require.NoError(t, err) - require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) - - // Check that restoring the key gets the same results - restoredKey, err := kb.Key("some_account") - require.NoError(t, err) - require.NotNil(t, restoredKey) - require.Equal(t, "some_account", restoredKey.GetName()) - require.Equal(t, TypeLedger, restoredKey.GetType()) - pubKey = restoredKey.GetPubKey() - pk, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) - require.NoError(t, err) - require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) - - path, err := restoredKey.GetPath() - require.NoError(t, err) - require.Equal(t, "44'/118'/3'/0/1", path.String()) -} - -// TestInMemoryKeyManagement makes sure we can manipulate these keys well -func TestInMemoryKeyManagement(t *testing.T) { - // make the storage with reasonable defaults - cstore := NewInMemory() - - algo := AltSecp256k1 - n1, n2, n3 := "personal", "business", "other" - - // Check empty state - l, err := cstore.List() - require.Nil(t, err) - require.Empty(t, l) - - _, _, err = cstore.NewMnemonic(n1, English, notSupportedAlgo{}) - require.Error(t, err, "ed25519 keys are currently not supported by keybase") - - // create some keys - _, err = cstore.Key(n1) - require.Error(t, err) - i, _, err := cstore.NewMnemonic(n1, English, algo) - - require.NoError(t, err) - require.Equal(t, n1, i.GetName()) - _, _, err = cstore.NewMnemonic(n2, English, algo) - require.NoError(t, err) - - // we can get these keys - i2, err := cstore.Key(n2) - require.NoError(t, err) - _, err = cstore.Key(n3) - require.NotNil(t, err) - _, err = cstore.KeyByAddress(accAddr(i2)) - require.NoError(t, err) - addr, err := sdk.AccAddressFromBech32("cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t") - require.NoError(t, err) - _, err = cstore.KeyByAddress(addr) - require.NotNil(t, err) - - // list shows them in order - keyS, err := cstore.List() - require.NoError(t, err) - require.Equal(t, 2, len(keyS)) - // note these are in alphabetical order - require.Equal(t, n2, keyS[0].GetName()) - require.Equal(t, n1, keyS[1].GetName()) - require.Equal(t, i2.GetPubKey(), keyS[0].GetPubKey()) - - // deleting a key removes it - err = cstore.Delete("bad name") - require.NotNil(t, err) - err = cstore.Delete(n1) - require.NoError(t, err) - keyS, err = cstore.List() - require.NoError(t, err) - require.Equal(t, 1, len(keyS)) - _, err = cstore.Key(n1) - require.Error(t, err) - - // create an offline key - o1 := "offline" - priv1 := ed25519.GenPrivKey() - pub1 := priv1.PubKey() - i, err = cstore.SavePubKey(o1, pub1, Ed25519) - require.Nil(t, err) - require.Equal(t, pub1, i.GetPubKey()) - require.Equal(t, o1, i.GetName()) - iOffline := i.(*offlineInfo) - require.Equal(t, Ed25519, iOffline.GetAlgo()) - keyS, err = cstore.List() - require.NoError(t, err) - require.Equal(t, 2, len(keyS)) - - // delete the offline key - err = cstore.Delete(o1) - require.NoError(t, err) - keyS, err = cstore.List() - require.NoError(t, err) - require.Equal(t, 1, len(keyS)) - - // addr cache gets nuked - and test skip flag - err = cstore.Delete(n2) - require.NoError(t, err) -} - -// TestInMemorySignVerify does some detailed checks on how we sign and validate -// signatures -func TestInMemorySignVerify(t *testing.T) { - cstore := NewInMemory() - algo := AltSecp256k1 - - n1, n2, n3 := "some dude", "a dudette", "dude-ish" - - // create two users and get their info - i1, _, err := cstore.NewMnemonic(n1, English, algo) - require.Nil(t, err) - - i2, _, err := cstore.NewMnemonic(n2, English, algo) - require.Nil(t, err) - - // Import a public key - armor, err := cstore.ExportPubKeyArmor(n2) - require.Nil(t, err) - err = cstore.ImportPubKey(n3, armor) - require.NoError(t, err) - i3, err := cstore.Key(n3) - require.NoError(t, err) - require.Equal(t, i3.GetName(), n3) - - // let's try to sign some messages - d1 := []byte("my first message") - d2 := []byte("some other important info!") - d3 := []byte("feels like I forgot something...") - - // try signing both data with both .. - s11, pub1, err := cstore.Sign(n1, d1) - require.Nil(t, err) - require.Equal(t, i1.GetPubKey(), pub1) - - s12, pub1, err := cstore.Sign(n1, d2) - require.Nil(t, err) - require.Equal(t, i1.GetPubKey(), pub1) - - s21, pub2, err := cstore.Sign(n2, d1) - require.Nil(t, err) - require.Equal(t, i2.GetPubKey(), pub2) - - s22, pub2, err := cstore.Sign(n2, d2) - require.Nil(t, err) - require.Equal(t, i2.GetPubKey(), pub2) - - // let's try to validate and make sure it only works when everything is proper - cases := []struct { - key tmcrypto.PubKey - data []byte - sig []byte - valid bool - }{ - // proper matches - {i1.GetPubKey(), d1, s11, true}, - // change data, pubkey, or signature leads to fail - {i1.GetPubKey(), d2, s11, false}, - {i2.GetPubKey(), d1, s11, false}, - {i1.GetPubKey(), d1, s21, false}, - // make sure other successes - {i1.GetPubKey(), d2, s12, true}, - {i2.GetPubKey(), d1, s21, true}, - {i2.GetPubKey(), d2, s22, true}, - } - - for i, tc := range cases { - valid := tc.key.VerifyBytes(tc.data, tc.sig) - require.Equal(t, tc.valid, valid, "%d", i) - } - - // Now try to sign data with a secret-less key - _, _, err = cstore.Sign(n3, d3) - require.Error(t, err) - require.Equal(t, "cannot sign with offline keys", err.Error()) -} - -// TestInMemoryExportImport tests exporting and importing -func TestInMemoryExportImport(t *testing.T) { - // make the storage with reasonable defaults - cstore := NewInMemory() - - info, _, err := cstore.NewMnemonic("john", English, AltSecp256k1) - require.NoError(t, err) - require.Equal(t, info.GetName(), "john") - - john, err := cstore.Key("john") - require.NoError(t, err) - require.Equal(t, info.GetName(), "john") - johnAddr := info.GetPubKey().Address() - - armor, err := cstore.ExportPubKeyArmor("john") - require.NoError(t, err) - - err = cstore.ImportPubKey("john2", armor) - require.NoError(t, err) - - john2, err := cstore.Key("john2") - require.NoError(t, err) - - require.Equal(t, john.GetPubKey().Address(), johnAddr) - require.Equal(t, john.GetName(), "john") - require.Equal(t, john.GetAddress(), john2.GetAddress()) - require.Equal(t, john.GetAlgo(), john2.GetAlgo()) - require.Equal(t, john.GetPubKey(), john2.GetPubKey()) -} - -func TestInMemoryExportImportPrivKey(t *testing.T) { - kb := NewInMemory() - - info, _, err := kb.NewMnemonic("john", English, AltSecp256k1) - require.NoError(t, err) - require.Equal(t, info.GetName(), "john") - priv1, err := kb.Key("john") - require.NoError(t, err) - - armored, err := kb.ExportPrivKeyArmor("john", "secretcpw") - require.NoError(t, err) - - // delete exported key - require.NoError(t, kb.Delete("john")) - _, err = kb.Key("john") - require.Error(t, err) - - // import armored key - require.NoError(t, kb.ImportPrivKey("john", armored, "secretcpw")) - - // ensure old and new keys match - priv2, err := kb.Key("john") - require.NoError(t, err) - require.True(t, priv1.GetPubKey().Equals(priv2.GetPubKey())) -} - -func TestInMemoryExportImportPubKey(t *testing.T) { - // make the storage with reasonable defaults - cstore := NewInMemory() - - // CreateMnemonic a private-public key pair and ensure consistency - info, _, err := cstore.NewMnemonic("john", English, AltSecp256k1) - require.Nil(t, err) - require.NotEqual(t, info, "") - require.Equal(t, info.GetName(), "john") - addr := info.GetPubKey().Address() - john, err := cstore.Key("john") - require.NoError(t, err) - require.Equal(t, john.GetName(), "john") - require.Equal(t, john.GetPubKey().Address(), addr) - - // Export the public key only - armor, err := cstore.ExportPubKeyArmor("john") - require.NoError(t, err) - // Import it under a different name - err = cstore.ImportPubKey("john-pubkey-only", armor) - require.NoError(t, err) - // Ensure consistency - john2, err := cstore.Key("john-pubkey-only") - require.NoError(t, err) - // Compare the public keys - require.True(t, john.GetPubKey().Equals(john2.GetPubKey())) - // Ensure the original key hasn't changed - john, err = cstore.Key("john") - require.NoError(t, err) - require.Equal(t, john.GetPubKey().Address(), addr) - require.Equal(t, john.GetName(), "john") - - // Ensure keys cannot be overwritten - err = cstore.ImportPubKey("john-pubkey-only", armor) - require.NotNil(t, err) -} - -// TestInMemoryAdvancedKeyManagement verifies update, import, export functionality -func TestInMemoryAdvancedKeyManagement(t *testing.T) { - // make the storage with reasonable defaults - cstore := NewInMemory() - - algo := AltSecp256k1 - n1, n2 := "old-name", "new name" - - // make sure key works with initial password - _, _, err := cstore.NewMnemonic(n1, English, algo) - require.Nil(t, err, "%+v", err) - - // exporting requires the proper name and passphrase - _, err = cstore.ExportPubKeyArmor(n1 + ".notreal") - require.NotNil(t, err) - _, err = cstore.ExportPubKeyArmor(" " + n1) - require.NotNil(t, err) - _, err = cstore.ExportPubKeyArmor(n1 + " ") - require.NotNil(t, err) - _, err = cstore.ExportPubKeyArmor("") - require.NotNil(t, err) - exported, err := cstore.ExportPubKeyArmor(n1) - require.Nil(t, err, "%+v", err) - - // import succeeds - err = cstore.ImportPubKey(n2, exported) - require.NoError(t, err) - - // second import fails - err = cstore.ImportPubKey(n2, exported) - require.NotNil(t, err) -} - -// TestInMemorySeedPhrase verifies restoring from a seed phrase -func TestInMemorySeedPhrase(t *testing.T) { - - // make the storage with reasonable defaults - cstore := NewInMemory() - - algo := AltSecp256k1 - n1, n2 := "lost-key", "found-again" - - // make sure key works with initial password - info, mnemonic, err := cstore.NewMnemonic(n1, English, algo) - require.Nil(t, err, "%+v", err) - require.Equal(t, n1, info.GetName()) - require.NotEmpty(t, mnemonic) - - // now, let us delete this key - err = cstore.Delete(n1) - require.Nil(t, err, "%+v", err) - _, err = cstore.Key(n1) - require.NotNil(t, err) - - // let us re-create it from the mnemonic-phrase - params := *hd.NewFundraiserParams(0, sdk.CoinType, 0) - hdPath := params.String() - newInfo, err := cstore.NewAccount(n2, mnemonic, DefaultBIP39Passphrase, hdPath, algo) - require.NoError(t, err) - require.Equal(t, n2, newInfo.GetName()) - require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) - require.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) -} - -func ExampleNew() { - // Select the encryption and storage for your cryptostore - cstore := NewInMemory() - - sec := AltSecp256k1 - - // Add keys and see they return in alphabetical order - bob, _, err := cstore.NewMnemonic("Bob", English, sec) - if err != nil { - // this should never happen - fmt.Println(err) - } else { - // return info here just like in List - fmt.Println(bob.GetName()) - } - _, _, _ = cstore.NewMnemonic("Alice", English, sec) - _, _, _ = cstore.NewMnemonic("Carl", English, sec) - info, _ := cstore.List() - for _, i := range info { - fmt.Println(i.GetName()) - } - - // We need to use passphrase to generate a signature - tx := []byte("deadbeef") - sig, pub, err := cstore.Sign("Bob", tx) - if err != nil { - fmt.Println("don't accept real passphrase") - } - - // and we can validate the signature with publicly available info - binfo, _ := cstore.Key("Bob") - if !binfo.GetPubKey().Equals(bob.GetPubKey()) { - fmt.Println("Get and Create return different keys") - } - - if pub.Equals(binfo.GetPubKey()) { - fmt.Println("signed by Bob") - } - if !pub.VerifyBytes(tx, sig) { - fmt.Println("invalid signature") - } - - // Output: - // Bob - // Alice - // Bob - // Carl - // signed by Bob -} - -func accAddr(info Info) sdk.AccAddress { - return sdk.AccAddress(info.GetPubKey().Address()) -} From b211603739521c0dcf31b64dc8cd8655fe73e78f Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 2 Apr 2020 23:19:28 +0200 Subject: [PATCH 105/148] Substitue deprecate types with new ones --- client/keys/add_ledger_test.go | 6 +- client/keys/delete.go | 34 +- client/keys/delete_test.go | 62 +- client/keys/export.go | 8 +- client/keys/import.go | 2 +- client/keys/list.go | 2 +- crypto/keyring/alt_signing_algorithms.go | 56 -- crypto/keyring/altkeyring.go | 481 --------------- crypto/keyring/doc.go | 4 +- crypto/keyring/keybase.go | 76 --- crypto/keyring/keyring.go | 550 ++++++++++-------- .../{altkeyring_test.go => keyring_test.go} | 0 crypto/keyring/signing_algorithms.go | 55 ++ ...hms_test.go => signing_algorithms_test.go} | 2 +- x/auth/client/cli/tx_multisign.go | 4 +- x/genutil/client/cli/gentx.go | 4 +- 16 files changed, 386 insertions(+), 960 deletions(-) delete mode 100644 crypto/keyring/alt_signing_algorithms.go delete mode 100644 crypto/keyring/altkeyring.go delete mode 100644 crypto/keyring/keybase.go rename crypto/keyring/{altkeyring_test.go => keyring_test.go} (100%) rename crypto/keyring/{alt_signing_algorithms_test.go => signing_algorithms_test.go} (97%) diff --git a/client/keys/add_ledger_test.go b/client/keys/add_ledger_test.go index 2fd57286996..de2920f51e0 100644 --- a/client/keys/add_ledger_test.go +++ b/client/keys/add_ledger_test.go @@ -50,14 +50,14 @@ func Test_runAddCmdLedgerWithCustomCoinType(t *testing.T) { require.NoError(t, runAddCmd(cmd, []string{"keyname1"})) // Now check that it has been stored properly - kb, err := keyring.NewKeyring(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn) + kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn) require.NoError(t, err) require.NotNil(t, kb) t.Cleanup(func() { - kb.Delete("keyname1", "", false) + kb.Delete("keyname1") }) mockIn.Reset("test1234\n") - key1, err := kb.Get("keyname1") + key1, err := kb.Key("keyname1") require.NoError(t, err) require.NotNil(t, key1) diff --git a/client/keys/delete.go b/client/keys/delete.go index a6631fa3bfb..ce0f8f4dc6c 100644 --- a/client/keys/delete.go +++ b/client/keys/delete.go @@ -2,7 +2,6 @@ package keys import ( "bufio" - "errors" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/input" @@ -54,38 +53,25 @@ func runDeleteCmd(cmd *cobra.Command, args []string) error { return err } - if info.GetType() == keyring.TypeLedger || info.GetType() == keyring.TypeOffline { - // confirm deletion, unless -y is passed - if !viper.GetBool(flagYes) { - if err := confirmDeletion(buf); err != nil { - return err - } - } - - if err := kb.Delete(name); err != nil { + // confirm deletion, unless -y is passed + if !viper.GetBool(flagYes) { + if yes, err := input.GetConfirmation("Key reference will be deleted. Continue?", buf); err != nil { return err + } else if !yes { + continue } - cmd.PrintErrln("Public key reference deleted") - return nil } - // old password and skip flag arguments are ignored if err := kb.Delete(name); err != nil { return err } + + if info.GetType() == keyring.TypeLedger || info.GetType() == keyring.TypeOffline { + cmd.PrintErrln("Public key reference deleted") + continue + } cmd.PrintErrln("Key deleted forever (uh oh!)") } return nil } - -func confirmDeletion(buf *bufio.Reader) error { - answer, err := input.GetConfirmation("Key reference will be deleted. Continue?", buf) - if err != nil { - return err - } - if !answer { - return errors.New("aborted") - } - return nil -} diff --git a/client/keys/delete_test.go b/client/keys/delete_test.go index 4f6df4131a7..e305b89e129 100644 --- a/client/keys/delete_test.go +++ b/client/keys/delete_test.go @@ -1,8 +1,6 @@ package keys import ( - "bufio" - "strings" "testing" "github.com/spf13/viper" @@ -20,18 +18,12 @@ func Test_runDeleteCmd(t *testing.T) { yesF, _ := deleteKeyCommand.Flags().GetBool(flagYes) forceF, _ := deleteKeyCommand.Flags().GetBool(flagForce) + require.False(t, yesF) require.False(t, forceF) fakeKeyName1 := "runDeleteCmd_Key1" fakeKeyName2 := "runDeleteCmd_Key2" - kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn) - require.NoError(t, err) - t.Cleanup(func() { - kb.Delete("runDeleteCmd_Key1") // nolint:errcheck - kb.Delete("runDeleteCmd_Key2") // nolint:errcheck - - }) // Now add a temporary keybase kbHome, cleanUp := tests.NewTestCaseDir(t) t.Cleanup(cleanUp) @@ -39,12 +31,12 @@ func Test_runDeleteCmd(t *testing.T) { // Now path := sdk.GetConfig().GetFullFundraiserPath() - kb, err = keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), kbHome, mockIn) + backend := viper.GetString(flags.FlagKeyringBackend) + kb, err := keyring.New(sdk.KeyringServiceName(), backend, kbHome, mockIn) require.NoError(t, err) _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, keyring.AltSecp256k1) require.NoError(t, err) - - _, err = kb.NewAccount(fakeKeyName2, tests.TestMnemonic, "", path, keyring.AltSecp256k1) + _, _, err = kb.NewMnemonic(fakeKeyName2, keyring.English, keyring.AltSecp256k1) require.NoError(t, err) err = runDeleteCmd(deleteKeyCommand, []string{"blah"}) @@ -56,17 +48,15 @@ func Test_runDeleteCmd(t *testing.T) { require.Error(t, err) require.Equal(t, "EOF", err.Error()) - { - _, err = kb.Key(fakeKeyName1) - require.NoError(t, err) + _, err = kb.Key(fakeKeyName1) + require.NoError(t, err) - // Now there is a confirmation - viper.Set(flagYes, true) - require.NoError(t, runDeleteCmd(deleteKeyCommand, []string{fakeKeyName1})) + // Now there is a confirmation + viper.Set(flagYes, true) + require.NoError(t, runDeleteCmd(deleteKeyCommand, []string{fakeKeyName1})) - _, err = kb.Key(fakeKeyName1) - require.Error(t, err) // Key1 is gone - } + _, err = kb.Key(fakeKeyName1) + require.Error(t, err) // Key1 is gone viper.Set(flagYes, true) _, err = kb.Key(fakeKeyName2) @@ -76,33 +66,3 @@ func Test_runDeleteCmd(t *testing.T) { _, err = kb.Key(fakeKeyName2) require.Error(t, err) // Key2 is gone } - -func Test_confirmDeletion(t *testing.T) { - type args struct { - buf *bufio.Reader - } - - answerYes := bufio.NewReader(strings.NewReader("y\n")) - answerYes2 := bufio.NewReader(strings.NewReader("Y\n")) - answerNo := bufio.NewReader(strings.NewReader("n\n")) - answerInvalid := bufio.NewReader(strings.NewReader("245\n")) - - tests := []struct { - name string - args args - wantErr bool - }{ - {"Y", args{answerYes}, false}, - {"y", args{answerYes2}, false}, - {"N", args{answerNo}, true}, - {"BAD", args{answerInvalid}, true}, - } - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - if err := confirmDeletion(tt.args.buf); (err != nil) != tt.wantErr { - t.Errorf("confirmDeletion() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} diff --git a/client/keys/export.go b/client/keys/export.go index dba66d8352a..2c17bfe84f7 100644 --- a/client/keys/export.go +++ b/client/keys/export.go @@ -25,21 +25,17 @@ func ExportKeyCommand() *cobra.Command { func runExportCmd(cmd *cobra.Command, args []string) error { buf := bufio.NewReader(cmd.InOrStdin()) - kb, err := keyring.NewKeyring(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), buf) + kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), buf) if err != nil { return err } - decryptPassword, err := input.GetPassword("Enter passphrase to decrypt your key:", buf) - if err != nil { - return err - } encryptPassword, err := input.GetPassword("Enter passphrase to encrypt the exported key:", buf) if err != nil { return err } - armored, err := kb.ExportPrivKey(args[0], decryptPassword, encryptPassword) + armored, err := kb.ExportPrivKeyArmor(args[0], encryptPassword) if err != nil { return err } diff --git a/client/keys/import.go b/client/keys/import.go index 89a1f3769f8..cbba4598dcb 100644 --- a/client/keys/import.go +++ b/client/keys/import.go @@ -26,7 +26,7 @@ func ImportKeyCommand() *cobra.Command { func runImportCmd(cmd *cobra.Command, args []string) error { buf := bufio.NewReader(cmd.InOrStdin()) - kb, err := keyring.NewKeyring(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), buf) + kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), buf) if err != nil { return err } diff --git a/client/keys/list.go b/client/keys/list.go index 770bde2f146..9ec4df43bf4 100644 --- a/client/keys/list.go +++ b/client/keys/list.go @@ -26,7 +26,7 @@ along with their associated name and address.`, } func runListCmd(cmd *cobra.Command, _ []string) error { - kb, err := keyring.NewKeyring(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), cmd.InOrStdin()) + kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), cmd.InOrStdin()) if err != nil { return err } diff --git a/crypto/keyring/alt_signing_algorithms.go b/crypto/keyring/alt_signing_algorithms.go deleted file mode 100644 index 8876c4a8f5c..00000000000 --- a/crypto/keyring/alt_signing_algorithms.go +++ /dev/null @@ -1,56 +0,0 @@ -package keyring - -import ( - "fmt" - - "github.com/tendermint/tendermint/crypto" -) - -type AltSigningAlgo interface { - Name() pubKeyType - DeriveKey() AltDeriveKeyFunc - PrivKeyGen() AltPrivKeyGenFunc -} - -type AltDeriveKeyFunc func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) -type AltPrivKeyGenFunc func(bz []byte) crypto.PrivKey - -func NewSigningAlgoFromString(str string) (AltSigningAlgo, error) { - if str != string(AltSecp256k1.Name()) { - return nil, fmt.Errorf("provided algorithm `%s` is not supported", str) - } - - return AltSecp256k1, nil -} - -type secp256k1Algo struct { -} - -func (s secp256k1Algo) Name() pubKeyType { - return Secp256k1 -} - -func (s secp256k1Algo) DeriveKey() AltDeriveKeyFunc { - return SecpDeriveKey -} - -func (s secp256k1Algo) PrivKeyGen() AltPrivKeyGenFunc { - return SecpPrivKeyGen -} - -var ( - // Secp256k1 uses the Bitcoin secp256k1 ECDSA parameters. - AltSecp256k1 = secp256k1Algo{} -) - -type AltSigningAlgoList []AltSigningAlgo - -func (l AltSigningAlgoList) Contains(algo AltSigningAlgo) bool { - for _, cAlgo := range l { - if cAlgo.Name() == algo.Name() { - return true - } - } - - return false -} diff --git a/crypto/keyring/altkeyring.go b/crypto/keyring/altkeyring.go deleted file mode 100644 index 8b65dd1d7cf..00000000000 --- a/crypto/keyring/altkeyring.go +++ /dev/null @@ -1,481 +0,0 @@ -package keyring - -import ( - "encoding/hex" - "fmt" - "io" - "sort" - "strings" - - "github.com/99designs/keyring" - "github.com/pkg/errors" - cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" - - "github.com/cosmos/cosmos-sdk/crypto" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" - "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/go-bip39" - tmcrypto "github.com/tendermint/tendermint/crypto" -) - -var ( - _ Keyring = &keystore{} -) - -// NewKeyring creates a new instance of a keyring. Keybase -// options can be applied when generating this new Keybase. -// Available backends are "os", "file", "kwallet", "pass", "test". -func New( - appName, backend, rootDir string, userInput io.Reader, opts ...AltKeyringOption, -) (Keyring, error) { - - var db keyring.Keyring - var err error - - switch backend { - case BackendMemory: - return NewInMemory(opts...), err - case BackendTest: - db, err = keyring.Open(lkbToKeyringConfig(appName, rootDir, nil, true)) - case BackendFile: - db, err = keyring.Open(newFileBackendKeyringConfig(appName, rootDir, userInput)) - case BackendOS: - db, err = keyring.Open(lkbToKeyringConfig(appName, rootDir, userInput, false)) - case BackendKWallet: - db, err = keyring.Open(newKWalletBackendKeyringConfig(appName, rootDir, userInput)) - case BackendPass: - db, err = keyring.Open(newPassBackendKeyringConfig(appName, rootDir, userInput)) - default: - return nil, fmt.Errorf("unknown keyring backend %v", backend) - } - - if err != nil { - return nil, err - } - - return newKeystore(db, opts...), nil -} - -type keystore struct { - db keyring.Keyring - options altKrOptions -} - -func newKeystore(kr keyring.Keyring, opts ...AltKeyringOption) keystore { - // Default options for keybase - options := altKrOptions{ - supportedAlgos: AltSigningAlgoList{AltSecp256k1}, - supportedAlgosLedger: AltSigningAlgoList{AltSecp256k1}, - } - - for _, optionFn := range opts { - optionFn(&options) - } - - return keystore{kr, options} -} - -func (ks keystore) ExportPubKeyArmor(uid string) (string, error) { - bz, err := ks.Key(uid) - if err != nil { - return "", err - } - - if bz == nil { - return "", fmt.Errorf("no key to export with name: %s", uid) - } - - return crypto.ArmorPubKeyBytes(bz.GetPubKey().Bytes(), string(bz.GetAlgo())), nil -} - -func (ks keystore) ExportPubKeyArmorByAddress(address types.Address) (string, error) { - info, err := ks.KeyByAddress(address) - if err != nil { - return "", err - } - - return ks.ExportPubKeyArmor(info.GetName()) -} - -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 -} - -// ExportPrivateKeyObject exports an armored private key object. -func (ks keystore) ExportPrivateKeyObject(uid string) (tmcrypto.PrivKey, error) { - info, err := ks.Key(uid) - if err != nil { - return nil, err - } - - var priv tmcrypto.PrivKey - - switch linfo := info.(type) { - case localInfo: - if linfo.PrivKeyArmor == "" { - err = fmt.Errorf("private key not available") - return nil, err - } - - priv, err = cryptoAmino.PrivKeyFromBytes([]byte(linfo.PrivKeyArmor)) - if err != nil { - return nil, err - } - - case ledgerInfo, offlineInfo, multiInfo: - return nil, errors.New("only works on local private keys") - } - - return priv, nil -} - -func (ks keystore) ExportPrivKeyArmorByAddress(address types.Address, encryptPassphrase string) (armor string, err error) { - byAddress, err := ks.KeyByAddress(address) - if err != nil { - return "", err - } - - return ks.ExportPrivKeyArmor(byAddress.GetName(), encryptPassphrase) -} - -func (ks keystore) ImportPrivKey(uid, armor, passphrase string) error { - if _, err := ks.Key(uid); err == nil { - return fmt.Errorf("cannot overwrite key: %s", uid) - } - - privKey, algo, err := crypto.UnarmorDecryptPrivKey(armor, passphrase) - if err != nil { - return errors.Wrap(err, "failed to decrypt private key") - } - - _, err = ks.writeLocalKey(uid, privKey, pubKeyType(algo)) - if err != nil { - return err - } - - return nil -} - -func (ks keystore) ImportPubKey(uid string, armor string) error { - if _, err := ks.Key(uid); err == nil { - return fmt.Errorf("cannot overwrite key: %s", uid) - } - - pubBytes, algo, err := crypto.UnarmorPubKeyBytes(armor) - if err != nil { - return err - } - - pubKey, err := cryptoAmino.PubKeyFromBytes(pubBytes) - if err != nil { - return err - } - - _, err = ks.writeOfflineKey(uid, pubKey, pubKeyType(algo)) - if err != nil { - return err - } - - return nil -} - -func (ks keystore) Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error) { - info, err := ks.Key(uid) - if err != nil { - return nil, nil, err - } - - var priv tmcrypto.PrivKey - - switch i := info.(type) { - case localInfo: - if i.PrivKeyArmor == "" { - return nil, nil, fmt.Errorf("private key not available") - } - - priv, err = cryptoAmino.PrivKeyFromBytes([]byte(i.PrivKeyArmor)) - if err != nil { - return nil, nil, err - } - - case ledgerInfo: - return SignWithLedger(info, msg) - - case offlineInfo, multiInfo: - return nil, info.GetPubKey(), 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 types.Address, msg []byte) ([]byte, tmcrypto.PubKey, error) { - key, err := ks.KeyByAddress(address) - if err != nil { - return nil, nil, err - } - - return ks.Sign(key.GetName(), msg) -} - -func (ks keystore) SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, account, index uint32) (Info, error) { - if !ks.options.supportedAlgosLedger.Contains(algo) { - return nil, ErrUnsupportedSigningAlgo - } - - coinType := types.GetConfig().GetCoinType() - hdPath := hd.NewFundraiserParams(account, coinType, index) - - priv, _, err := crypto.NewPrivKeyLedgerSecp256k1(*hdPath, hrp) - if err != nil { - return nil, err - } - - return ks.writeLedgerKey(uid, priv.PubKey(), *hdPath, algo.Name()) -} - -func (ks keystore) writeLedgerKey(name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo pubKeyType) (Info, error) { - info := newLedgerInfo(name, pub, path, algo) - err := ks.writeInfo(name, info) - if err != nil { - return nil, err - } - - return info, nil -} - -type altKrOptions struct { - supportedAlgos AltSigningAlgoList - supportedAlgosLedger AltSigningAlgoList -} - -func (ks keystore) SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) { - return ks.writeMultisigKey(uid, pubkey) -} - -func (ks keystore) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo pubKeyType) (Info, error) { - return ks.writeOfflineKey(uid, pubkey, algo) -} - -func (ks keystore) DeleteByAddress(address types.Address) error { - info, err := ks.KeyByAddress(address) - if err != nil { - return err - } - - err = ks.Delete(info.GetName()) - if err != nil { - return err - } - - return nil -} - -func (ks keystore) Delete(uid string) error { - info, err := ks.Key(uid) - if err != nil { - return err - } - - err = ks.db.Remove(addrHexKeyAsString(info.GetAddress())) - if err != nil { - return err - } - - err = ks.db.Remove(string(infoKey(uid))) - if err != nil { - return err - } - - return nil -} - -func (ks keystore) KeyByAddress(address types.Address) (Info, error) { - ik, err := ks.db.Get(addrHexKeyAsString(address)) - if err != nil { - return nil, err - } - - if len(ik.Data) == 0 { - return nil, fmt.Errorf("key with address %s not found", address) - } - - bs, err := ks.db.Get(string(ik.Data)) - if err != nil { - return nil, err - } - - return unmarshalInfo(bs.Data) -} - -func (ks keystore) List() ([]Info, error) { - var res []Info - keys, err := ks.db.Keys() - if err != nil { - return nil, err - } - - 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) - } - } - - return res, nil -} - -func (ks keystore) NewMnemonic(uid string, language Language, algo AltSigningAlgo) (Info, string, error) { - if language != English { - return nil, "", ErrUnsupportedLanguage - } - - if !ks.isSupportedSigningAlgo(algo) { - return nil, "", ErrUnsupportedSigningAlgo - } - - // Default number of words (24): This generates a mnemonic directly from the - // number of words by reading system entropy. - entropy, err := bip39.NewEntropy(defaultEntropySize) - if err != nil { - return nil, "", err - } - - mnemonic, err := bip39.NewMnemonic(entropy) - if err != nil { - return nil, "", err - } - - info, err := ks.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, types.GetConfig().GetFullFundraiserPath(), algo) - if err != nil { - return nil, "", err - } - - return info, mnemonic, err -} - -func (ks keystore) NewAccount(uid string, mnemonic string, bip39Passphrase string, hdPath string, algo AltSigningAlgo) (Info, error) { - if !ks.isSupportedSigningAlgo(algo) { - return nil, ErrUnsupportedSigningAlgo - } - - // create master key and derive first key for keyring - derivedPriv, err := algo.DeriveKey()(mnemonic, bip39Passphrase, hdPath) - if err != nil { - return nil, err - } - - privKey := algo.PrivKeyGen()(derivedPriv) - - return ks.writeLocalKey(uid, privKey, algo.Name()) -} - -func (ks keystore) isSupportedSigningAlgo(algo AltSigningAlgo) bool { - return ks.options.supportedAlgos.Contains(algo) -} - -func (ks keystore) Key(uid string) (Info, error) { - key := infoKey(uid) - - bs, err := ks.db.Get(string(key)) - if err != nil { - return nil, err - } - - if len(bs.Data) == 0 { - return nil, sdkerrors.Wrap(sdkerrors.ErrKeyNotFound, uid) - } - - return unmarshalInfo(bs.Data) -} - -func (ks keystore) writeLocalKey(name string, priv tmcrypto.PrivKey, algo pubKeyType) (Info, error) { - // encrypt private key using keyring - pub := priv.PubKey() - - info := newLocalInfo(name, pub, string(priv.Bytes()), algo) - err := ks.writeInfo(name, info) - if err != nil { - return nil, err - } - - return info, nil -} - -func (ks keystore) writeInfo(name string, info Info) error { - // write the info by key - key := infoKey(name) - serializedInfo := marshalInfo(info) - - err := ks.db.Set(keyring.Item{ - Key: string(key), - Data: serializedInfo, - }) - if err != nil { - return err - } - - err = ks.db.Set(keyring.Item{ - Key: addrHexKeyAsString(info.GetAddress()), - Data: key, - }) - if err != nil { - return err - } - - return nil -} - -func (ks keystore) writeOfflineKey(name string, pub tmcrypto.PubKey, algo pubKeyType) (Info, error) { - info := newOfflineInfo(name, pub, algo) - err := ks.writeInfo(name, info) - if err != nil { - return nil, err - } - - return info, nil -} - -func (ks keystore) writeMultisigKey(name string, pub tmcrypto.PubKey) (Info, error) { - info := NewMultiInfo(name, pub) - err := ks.writeInfo(name, info) - if err != nil { - return nil, err - } - - return info, nil -} - -func addrHexKeyAsString(address types.Address) string { - return fmt.Sprintf("%s.%s", hex.EncodeToString(address.Bytes()), addressSuffix) -} diff --git a/crypto/keyring/doc.go b/crypto/keyring/doc.go index 369f053b76a..0a76866e4b4 100644 --- a/crypto/keyring/doc.go +++ b/crypto/keyring/doc.go @@ -19,9 +19,9 @@ // generated keys are discarded when the process terminates or the type instance is garbage // collected. // -// NewKeyring +// New // -// The NewKeyring constructor returns an implementation backed by a keyring library +// The New constructor returns an implementation backed by a keyring library // (https://github.com/99designs/keyring), whose aim is to provide a common abstraction and uniform // interface between secret stores available for Windows, macOS, and most GNU/Linux distributions // as well as operating system-agnostic encrypted file-based backends. diff --git a/crypto/keyring/keybase.go b/crypto/keyring/keybase.go deleted file mode 100644 index a88308abae9..00000000000 --- a/crypto/keyring/keybase.go +++ /dev/null @@ -1,76 +0,0 @@ -package keyring - -import ( - "github.com/tendermint/tendermint/crypto" - - "github.com/cosmos/cosmos-sdk/types" -) - -// Keybase exposes operations on a generic keystore -type Keybase interface { - // CRUD on the keystore - List() ([]Info, error) - // Get returns the public information about one key. - Get(name string) (Info, error) - // Get performs a by-address lookup and returns the public - // information about one key if there's any. - GetByAddress(address types.AccAddress) (Info, error) - // Delete removes a key. - Delete(name, passphrase string, skipPass bool) error - // Sign bytes, looking up the private key to use. - Sign(name, passphrase string, msg []byte) ([]byte, crypto.PubKey, error) - - // CreateMnemonic generates a new mnemonic, derives a hierarchical deterministic - // key from that. and persists it to storage, encrypted using the provided password. - // It returns the generated mnemonic and the key Info. It returns an error if it fails to - // generate a key for the given algo type, or if another key is already stored under the - // same name. - CreateMnemonic(name string, language Language, passwd string, algo pubKeyType) (info Info, seed string, err error) - - // CreateAccount converts a mnemonic to a private key and BIP 32 HD Path - // and persists it, encrypted with the given password. - CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd, hdPath string, algo pubKeyType) (Info, error) - - // CreateLedger creates, stores, and returns a new Ledger key reference - CreateLedger(name string, algo pubKeyType, hrp string, account, index uint32) (info Info, err error) - - // CreateOffline creates, stores, and returns a new offline key reference - CreateOffline(name string, pubkey crypto.PubKey, algo pubKeyType) (info Info, err error) - - // CreateMulti creates, stores, and returns a new multsig (offline) key reference - CreateMulti(name string, pubkey crypto.PubKey) (info Info, err error) - - // Import imports ASCII armored Info objects. - Import(name string, armor string) (err error) - - // ImportPrivKey imports a private key in ASCII armor format. - // It returns an error if a key with the same name exists or a wrong encryption passphrase is - // supplied. - ImportPrivKey(name, armor, passphrase string) error - - // ImportPubKey imports ASCII-armored public keys. - // Store a new Info object holding a public key only, i.e. it will - // not be possible to sign with it as it lacks the secret key. - ImportPubKey(name string, armor string) (err error) - - // Export exports an Info object in ASCII armored format. - Export(name string) (armor string, err error) - - // ExportPubKey returns public keys in ASCII armored format. - // Retrieve a Info object by its name and return the public key in - // a portable format. - ExportPubKey(name string) (armor string, err error) - - // 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. - ExportPrivKey(name, decryptPassphrase, encryptPassphrase string) (armor string, err error) - - // ExportPrivateKeyObject *only* works on locally-stored keys. Temporary method until we redo the exporting API - ExportPrivateKeyObject(name string, passphrase string) (crypto.PrivKey, error) - - // SupportedAlgos returns a list of signing algorithms supported by the keybase - SupportedAlgos() []pubKeyType - - // SupportedAlgosLedger returns a list of signing algorithms supported by the keybase's ledger integration - SupportedAlgosLedger() []pubKeyType -} diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 55835fe2ac7..aeb0347540b 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -2,6 +2,7 @@ package keyring import ( "bufio" + "encoding/hex" "fmt" "io" "io/ioutil" @@ -11,15 +12,16 @@ import ( "strings" "github.com/99designs/keyring" + "github.com/cosmos/go-bip39" "github.com/pkg/errors" - "github.com/tendermint/crypto/bcrypt" tmcrypto "github.com/tendermint/tendermint/crypto" cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" "github.com/cosmos/cosmos-sdk/client/input" "github.com/cosmos/cosmos-sdk/crypto" - "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -38,6 +40,11 @@ const ( passKeyringPrefix = keyringDirNameFmt ) +var ( + _ Keyring = &keystore{} + maxPassphraseEntryAttempts = 3 +) + // Keyring exposes operations over a backend supported by github.com/99designs/keyring. type Keyring interface { // List all keys. @@ -45,23 +52,23 @@ type Keyring interface { // Key and KeyByAddress return keys by uid and address respectively. Key(uid string) (Info, error) - KeyByAddress(address types.Address) (Info, error) + KeyByAddress(address sdk.Address) (Info, error) // Delete and DeleteByAddress remove keys from the keyring. Delete(uid string) error - DeleteByAddress(address types.Address) error + DeleteByAddress(address sdk.Address) error // NewMnemonic generates a new mnemonic, derives a hierarchical deterministic // key from that, and persists it to the storage. Returns the generated mnemonic and the key // Info. It returns an error if it fails to generate a key for the given algo type, or if // another key is already stored under the same name. - NewMnemonic(uid string, language Language, algo AltSigningAlgo) (Info, string, error) + NewMnemonic(uid string, language Language, algo SigningAlgo) (Info, string, error) // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. - NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo AltSigningAlgo) (Info, error) + NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SigningAlgo) (Info, error) // SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. - SaveLedgerKey(uid string, algo AltSigningAlgo, hrp string, account, index uint32) (Info, error) + SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) // SavePubKey stores a public key and returns the persisted Info structure. SavePubKey(uid string, pubkey tmcrypto.PubKey, algo pubKeyType) (Info, error) @@ -81,7 +88,7 @@ type Signer interface { Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error) // SignByAddress sign byte messages with a user key providing the address. - SignByAddress(address types.Address, msg []byte) ([]byte, tmcrypto.PubKey, error) + SignByAddress(address sdk.Address, msg []byte) ([]byte, tmcrypto.PubKey, error) } // Importer is implemented by key stores that support import of public and private keys. @@ -94,44 +101,35 @@ type Importer interface { type Exporter interface { // Export public key ExportPubKeyArmor(uid string) (string, error) - ExportPubKeyArmorByAddress(address types.Address) (string, error) + ExportPubKeyArmorByAddress(address sdk.Address) (string, error) // 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. ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) - ExportPrivKeyArmorByAddress(address types.Address, encryptPassphrase string) (armor string, err error) + ExportPrivKeyArmorByAddress(address sdk.Address, encryptPassphrase string) (armor string, err error) } type AltKeyringOption func(options *altKrOptions) -// keyringKeybase implements the Keybase interface by using the Keyring library -// for account key persistence. -type keyringKeybase struct { - base baseKeybase - db keyring.Keyring -} - -var maxPassphraseEntryAttempts = 3 - -func newKeyringKeybase(db keyring.Keyring, opts ...KeybaseOption) Keybase { - return keyringKeybase{ - db: db, - base: newBaseKeybase(opts...), - } +// 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 ...AltKeyringOption) Keyring { + return newKeystore(keyring.NewArrayKeyring(nil), opts...) } -// NewKeyring creates a new instance of a keyring. Keybase -// options can be applied when generating this new Keybase. -// Available backends are "os", "file", "kwallet", "pass", "test". -func NewKeyring( - appName, backend, rootDir string, userInput io.Reader, opts ...KeybaseOption, -) (Keybase, error) { +// NewKeyring 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 ...AltKeyringOption, +) (Keyring, error) { var db keyring.Keyring var err error switch backend { case BackendMemory: - panic("not implemented") + return NewInMemory(opts...), err case BackendTest: db, err = keyring.Open(lkbToKeyringConfig(appName, rootDir, nil, true)) case BackendFile: @@ -145,135 +143,151 @@ func NewKeyring( default: return nil, fmt.Errorf("unknown keyring backend %v", backend) } + if err != nil { return nil, err } - return newKeyringKeybase(db, opts...), nil + return newKeystore(db, opts...), nil } -// 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 ...AltKeyringOption) Keyring { - return newKeystore(keyring.NewArrayKeyring(nil), opts...) +type keystore struct { + db keyring.Keyring + options altKrOptions } -// CreateMnemonic generates a new key and persists it to storage, encrypted -// using the provided password. It returns the generated mnemonic and the key Info. -// An error is returned if it fails to generate a key for the given algo type, -// or if another key is already stored under the same name. -func (kb keyringKeybase) CreateMnemonic( - name string, language Language, passwd string, algo pubKeyType, -) (info Info, mnemonic string, err error) { +func newKeystore(kr keyring.Keyring, opts ...AltKeyringOption) keystore { + // Default options for keybase + options := altKrOptions{ + supportedAlgos: AltSigningAlgoList{AltSecp256k1}, + supportedAlgosLedger: AltSigningAlgoList{AltSecp256k1}, + } + + for _, optionFn := range opts { + optionFn(&options) + } - return kb.base.CreateMnemonic(kb, name, language, passwd, algo) + return keystore{kr, options} } -// CreateAccount converts a mnemonic to a private key and persists it, encrypted -// with the given password. -func (kb keyringKeybase) CreateAccount( - name, mnemonic, bip39Passwd, encryptPasswd, hdPath string, algo pubKeyType, -) (Info, error) { +func (ks keystore) ExportPubKeyArmor(uid string) (string, error) { + bz, err := ks.Key(uid) + if err != nil { + return "", err + } + + if bz == nil { + return "", fmt.Errorf("no key to export with name: %s", uid) + } - return kb.base.CreateAccount(kb, name, mnemonic, bip39Passwd, encryptPasswd, hdPath, algo) + return crypto.ArmorPubKeyBytes(bz.GetPubKey().Bytes(), string(bz.GetAlgo())), nil } -// CreateLedger creates a new locally-stored reference to a Ledger keypair. -// It returns the created key info and an error if the Ledger could not be queried. -func (kb keyringKeybase) CreateLedger( - name string, algo pubKeyType, hrp string, account, index uint32, -) (Info, error) { +func (ks keystore) ExportPubKeyArmorByAddress(address sdk.Address) (string, error) { + info, err := ks.KeyByAddress(address) + if err != nil { + return "", err + } - return kb.base.CreateLedger(kb, name, algo, hrp, account, index) + return ks.ExportPubKeyArmor(info.GetName()) } -// CreateOffline creates a new reference to an offline keypair. It returns the -// created key info. -func (kb keyringKeybase) CreateOffline(name string, pub tmcrypto.PubKey, algo pubKeyType) (Info, error) { - return kb.base.writeOfflineKey(kb, name, pub, algo), nil -} +func (ks keystore) ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) { + priv, err := ks.ExportPrivateKeyObject(uid) + if err != nil { + return "", err + } -// CreateMulti creates a new reference to a multisig (offline) keypair. It -// returns the created key Info object. -func (kb keyringKeybase) CreateMulti(name string, pub tmcrypto.PubKey) (Info, error) { - return kb.base.writeMultisigKey(kb, name, pub), nil + info, err := ks.Key(uid) + if err != nil { + return "", err + } + + return crypto.EncryptArmorPrivKey(priv, encryptPassphrase, string(info.GetAlgo())), nil } -// List returns the keys from storage in alphabetical order. -func (kb keyringKeybase) List() ([]Info, error) { - var res []Info - keys, err := kb.db.Keys() +// ExportPrivateKeyObject exports an armored private key object. +func (ks keystore) ExportPrivateKeyObject(uid string) (tmcrypto.PrivKey, error) { + info, err := ks.Key(uid) if err != nil { return nil, err } - sort.Strings(keys) + var priv tmcrypto.PrivKey - for _, key := range keys { - if strings.HasSuffix(key, infoSuffix) { - rawInfo, err := kb.db.Get(key) - if err != nil { - return nil, err - } + switch linfo := info.(type) { + case localInfo: + if linfo.PrivKeyArmor == "" { + err = fmt.Errorf("private key not available") + return nil, err + } - if len(rawInfo.Data) == 0 { - return nil, sdkerrors.Wrap(sdkerrors.ErrKeyNotFound, key) - } + priv, err = cryptoAmino.PrivKeyFromBytes([]byte(linfo.PrivKeyArmor)) + if err != nil { + return nil, err + } - info, err := unmarshalInfo(rawInfo.Data) - if err != nil { - return nil, err - } + case ledgerInfo, offlineInfo, multiInfo: + return nil, errors.New("only works on local private keys") + } - res = append(res, info) - } + return priv, nil +} + +func (ks keystore) ExportPrivKeyArmorByAddress(address sdk.Address, encryptPassphrase string) (armor string, err error) { + byAddress, err := ks.KeyByAddress(address) + if err != nil { + return "", err } - return res, nil + return ks.ExportPrivKeyArmor(byAddress.GetName(), encryptPassphrase) } -// Get returns the public information about one key. -func (kb keyringKeybase) Get(name string) (Info, error) { - key := infoKey(name) +func (ks keystore) ImportPrivKey(uid, armor, passphrase string) error { + if _, err := ks.Key(uid); err == nil { + return fmt.Errorf("cannot overwrite key: %s", uid) + } - bs, err := kb.db.Get(string(key)) + privKey, algo, err := crypto.UnarmorDecryptPrivKey(armor, passphrase) if err != nil { - return nil, err + return errors.Wrap(err, "failed to decrypt private key") } - if len(bs.Data) == 0 { - return nil, sdkerrors.Wrap(sdkerrors.ErrKeyNotFound, name) + _, err = ks.writeLocalKey(uid, privKey, pubKeyType(algo)) + if err != nil { + return err } - return unmarshalInfo(bs.Data) + return nil } -// GetByAddress fetches a key by address and returns its public information. -func (kb keyringKeybase) GetByAddress(address types.AccAddress) (Info, error) { - ik, err := kb.db.Get(string(addrHexKey(address))) +func (ks keystore) ImportPubKey(uid string, armor string) error { + if _, err := ks.Key(uid); err == nil { + return fmt.Errorf("cannot overwrite key: %s", uid) + } + + pubBytes, algo, err := crypto.UnarmorPubKeyBytes(armor) if err != nil { - return nil, err + return err } - if len(ik.Data) == 0 { - return nil, fmt.Errorf("key with address %s not found", address) + pubKey, err := cryptoAmino.PubKeyFromBytes(pubBytes) + if err != nil { + return err } - bs, err := kb.db.Get(string(ik.Data)) + _, err = ks.writeOfflineKey(uid, pubKey, pubKeyType(algo)) if err != nil { - return nil, err + return err } - return unmarshalInfo(bs.Data) + return nil } -// Sign signs an arbitrary set of bytes with the named key. It returns an error -// if the key doesn't exist or the decryption fails. -func (kb keyringKeybase) Sign(name, passphrase string, msg []byte) (sig []byte, pub tmcrypto.PubKey, err error) { - info, err := kb.Get(name) +func (ks keystore) Sign(uid string, msg []byte) ([]byte, tmcrypto.PubKey, error) { + info, err := ks.Key(uid) if err != nil { - return + return nil, nil, err } var priv tmcrypto.PrivKey @@ -296,7 +310,7 @@ func (kb keyringKeybase) Sign(name, passphrase string, msg []byte) (sig []byte, return nil, info.GetPubKey(), errors.New("cannot sign with offline keys") } - sig, err = priv.Sign(msg) + sig, err := priv.Sign(msg) if err != nil { return nil, nil, err } @@ -304,91 +318,80 @@ func (kb keyringKeybase) Sign(name, passphrase string, msg []byte) (sig []byte, return sig, priv.PubKey(), nil } -// ExportPrivateKeyObject exports an armored private key object. -func (kb keyringKeybase) ExportPrivateKeyObject(name string, passphrase string) (tmcrypto.PrivKey, error) { - info, err := kb.Get(name) +func (ks keystore) SignByAddress(address sdk.Address, msg []byte) ([]byte, tmcrypto.PubKey, error) { + key, err := ks.KeyByAddress(address) if err != nil { - return nil, err + return nil, nil, err } - var priv tmcrypto.PrivKey - - switch linfo := info.(type) { - case localInfo: - if linfo.PrivKeyArmor == "" { - err = fmt.Errorf("private key not available") - return nil, err - } - - priv, err = cryptoAmino.PrivKeyFromBytes([]byte(linfo.PrivKeyArmor)) - if err != nil { - return nil, err - } + return ks.Sign(key.GetName(), msg) +} - case ledgerInfo, offlineInfo, multiInfo: - return nil, errors.New("only works on local private keys") +func (ks keystore) SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) { + if !ks.options.supportedAlgosLedger.Contains(algo) { + return nil, ErrUnsupportedSigningAlgo } - return priv, nil -} + coinType := sdk.GetConfig().GetCoinType() + hdPath := hd.NewFundraiserParams(account, coinType, index) -// Export exports armored private key to the caller. -func (kb keyringKeybase) Export(name string) (armor string, err error) { - bz, err := kb.db.Get(string(infoKey(name))) + priv, _, err := crypto.NewPrivKeyLedgerSecp256k1(*hdPath, hrp) if err != nil { - return "", err - } - - if bz.Data == nil { - return "", fmt.Errorf("no key to export with name: %s", name) + return nil, err } - return crypto.ArmorInfoBytes(bz.Data), nil + return ks.writeLedgerKey(uid, priv.PubKey(), *hdPath, algo.Name()) } -// ExportPubKey returns public keys in ASCII armored format. It retrieves an Info -// object by its name and return the public key in a portable format. -func (kb keyringKeybase) ExportPubKey(name string) (armor string, err error) { - bz, err := kb.Get(name) +func (ks keystore) writeLedgerKey(name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo pubKeyType) (Info, error) { + info := newLedgerInfo(name, pub, path, algo) + err := ks.writeInfo(name, info) if err != nil { - return "", err + return nil, err } - if bz == nil { - return "", fmt.Errorf("no key to export with name: %s", name) - } + return info, nil +} - return crypto.ArmorPubKeyBytes(bz.GetPubKey().Bytes(), string(bz.GetAlgo())), nil +type altKrOptions struct { + supportedAlgos AltSigningAlgoList + supportedAlgosLedger AltSigningAlgoList } -// Import imports armored private key. -func (kb keyringKeybase) Import(name string, armor string) error { - bz, _ := kb.Get(name) +func (ks keystore) SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) { + return ks.writeMultisigKey(uid, pubkey) +} - if bz != nil { - pubkey := bz.GetPubKey() +func (ks keystore) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo pubKeyType) (Info, error) { + return ks.writeOfflineKey(uid, pubkey, algo) +} - if len(pubkey.Bytes()) > 0 { - return fmt.Errorf("cannot overwrite data for name: %s", name) - } +func (ks keystore) DeleteByAddress(address sdk.Address) error { + info, err := ks.KeyByAddress(address) + if err != nil { + return err } - infoBytes, err := crypto.UnarmorInfoBytes(armor) + err = ks.Delete(info.GetName()) if err != nil { return err } - info, err := unmarshalInfo(infoBytes) + return nil +} + +func (ks keystore) Delete(uid string) error { + info, err := ks.Key(uid) if err != nil { return err } - kb.writeInfo(name, info) + err = ks.db.Remove(addrHexKeyAsString(info.GetAddress())) + if err != nil { + return err + } - err = kb.db.Set(keyring.Item{ - Key: string(addrHexKey(info.GetAddress())), - Data: infoKey(name), - }) + err = ks.db.Remove(string(infoKey(uid))) if err != nil { return err } @@ -396,136 +399,118 @@ func (kb keyringKeybase) Import(name string, armor string) error { return nil } -// ExportPrivKey returns a private key in ASCII armored format. An error is returned -// if the key does not exist or a wrong encryption passphrase is supplied. -func (kb keyringKeybase) ExportPrivKey(name, decryptPassphrase, encryptPassphrase string) (armor string, err error) { - priv, err := kb.ExportPrivateKeyObject(name, decryptPassphrase) +func (ks keystore) KeyByAddress(address sdk.Address) (Info, error) { + ik, err := ks.db.Get(addrHexKeyAsString(address)) if err != nil { - return "", err + return nil, err } - info, err := kb.Get(name) + if len(ik.Data) == 0 { + return nil, fmt.Errorf("key with address %s not found", address) + } + + bs, err := ks.db.Get(string(ik.Data)) if err != nil { - return "", err + return nil, err } - return crypto.EncryptArmorPrivKey(priv, encryptPassphrase, string(info.GetAlgo())), nil + return unmarshalInfo(bs.Data) } -// ImportPrivKey imports a private key in ASCII armor format. An error is returned -// if a key with the same name exists or a wrong encryption passphrase is -// supplied. -func (kb keyringKeybase) ImportPrivKey(name, armor, passphrase string) error { - if kb.HasKey(name) { - return fmt.Errorf("cannot overwrite key: %s", name) - } - - privKey, algo, err := crypto.UnarmorDecryptPrivKey(armor, passphrase) +func (ks keystore) List() ([]Info, error) { + var res []Info + keys, err := ks.db.Keys() if err != nil { - return errors.Wrap(err, "failed to decrypt private key") + return nil, err } - // NOTE: The keyring keystore has no need for a passphrase. - kb.writeLocalKey(name, privKey, pubKeyType(algo)) - return nil -} + sort.Strings(keys) -// HasKey returns whether the key exists in the keyring. -func (kb keyringKeybase) HasKey(name string) bool { - bz, _ := kb.Get(name) - return bz != nil -} + 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) + } -// ImportPubKey imports an ASCII-armored public key. It will store a new Info -// object holding a public key only, i.e. it will not be possible to sign with -// it as it lacks the secret key. -func (kb keyringKeybase) ImportPubKey(name string, armor string) error { - bz, _ := kb.Get(name) - if bz != nil { - pubkey := bz.GetPubKey() + info, err := unmarshalInfo(rawInfo.Data) + if err != nil { + return nil, err + } - if len(pubkey.Bytes()) > 0 { - return fmt.Errorf("cannot overwrite data for name: %s", name) + res = append(res, info) } } - pubBytes, algo, err := crypto.UnarmorPubKeyBytes(armor) - if err != nil { - return err - } + return res, nil +} - pubKey, err := cryptoAmino.PubKeyFromBytes(pubBytes) - if err != nil { - return err +func (ks keystore) NewMnemonic(uid string, language Language, algo SigningAlgo) (Info, string, error) { + if language != English { + return nil, "", ErrUnsupportedLanguage } - kb.base.writeOfflineKey(kb, name, pubKey, pubKeyType(algo)) - return nil -} + if !ks.isSupportedSigningAlgo(algo) { + return nil, "", ErrUnsupportedSigningAlgo + } -// Delete removes key forever, but we must present the proper passphrase before -// deleting it (for security). It returns an error if the key doesn't exist or -// passphrases don't match. The passphrase is ignored when deleting references to -// offline and Ledger / HW wallet keys. -func (kb keyringKeybase) Delete(name, _ string, _ bool) error { - // verify we have the proper password before deleting - info, err := kb.Get(name) + // Default number of words (24): This generates a mnemonic directly from the + // number of words by reading system entropy. + entropy, err := bip39.NewEntropy(defaultEntropySize) if err != nil { - return err + return nil, "", err } - err = kb.db.Remove(string(addrHexKey(info.GetAddress()))) + mnemonic, err := bip39.NewMnemonic(entropy) if err != nil { - return err + return nil, "", err } - err = kb.db.Remove(string(infoKey(name))) + info, err := ks.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.GetConfig().GetFullFundraiserPath(), algo) if err != nil { - return err + return nil, "", err } - return nil + return info, mnemonic, err } -// SupportedAlgos returns a list of supported signing algorithms. -func (kb keyringKeybase) SupportedAlgos() []pubKeyType { - return kb.base.SupportedAlgos() -} +func (ks keystore) NewAccount(uid string, mnemonic string, bip39Passphrase string, hdPath string, algo SigningAlgo) (Info, error) { + if !ks.isSupportedSigningAlgo(algo) { + return nil, ErrUnsupportedSigningAlgo + } -// SupportedAlgosLedger returns a list of supported ledger signing algorithms. -func (kb keyringKeybase) SupportedAlgosLedger() []pubKeyType { - return kb.base.SupportedAlgosLedger() -} + // create master key and derive first key for keyring + derivedPriv, err := algo.DeriveKey()(mnemonic, bip39Passphrase, hdPath) + if err != nil { + return nil, err + } -func (kb keyringKeybase) writeLocalKey(name string, priv tmcrypto.PrivKey, algo pubKeyType) Info { - // encrypt private key using keyring - pub := priv.PubKey() - info := newLocalInfo(name, pub, string(priv.Bytes()), algo) + privKey := algo.PrivKeyGen()(derivedPriv) - kb.writeInfo(name, info) - return info + return ks.writeLocalKey(uid, privKey, algo.Name()) } -func (kb keyringKeybase) writeInfo(name string, info Info) { - // write the info by key - key := infoKey(name) - serializedInfo := marshalInfo(info) +func (ks keystore) isSupportedSigningAlgo(algo SigningAlgo) bool { + return ks.options.supportedAlgos.Contains(algo) +} - err := kb.db.Set(keyring.Item{ - Key: string(key), - Data: serializedInfo, - }) +func (ks keystore) Key(uid string) (Info, error) { + key := infoKey(uid) + + bs, err := ks.db.Get(string(key)) if err != nil { - panic(err) + return nil, err } - err = kb.db.Set(keyring.Item{ - Key: string(addrHexKey(info.GetAddress())), - Data: key, - }) - if err != nil { - panic(err) + if len(bs.Data) == 0 { + return nil, sdkerrors.Wrap(sdkerrors.ErrKeyNotFound, uid) } + + return unmarshalInfo(bs.Data) } func lkbToKeyringConfig(appName, dir string, buf io.Reader, test bool) keyring.Config { @@ -648,6 +633,63 @@ func newRealPrompt(dir string, buf io.Reader) func(string) (string, error) { } } -func addrHexKey(address types.Address) []byte { - return []byte(addrHexKeyAsString(address)) +func (ks keystore) writeLocalKey(name string, priv tmcrypto.PrivKey, algo pubKeyType) (Info, error) { + // encrypt private key using keyring + pub := priv.PubKey() + + info := newLocalInfo(name, pub, string(priv.Bytes()), algo) + err := ks.writeInfo(name, info) + if err != nil { + return nil, err + } + + return info, nil +} + +func (ks keystore) writeInfo(name string, info Info) error { + // write the info by key + key := infoKey(name) + serializedInfo := marshalInfo(info) + + err := ks.db.Set(keyring.Item{ + Key: string(key), + Data: serializedInfo, + }) + if err != nil { + return err + } + + err = ks.db.Set(keyring.Item{ + Key: addrHexKeyAsString(info.GetAddress()), + Data: key, + }) + if err != nil { + return err + } + + return nil +} + +func (ks keystore) writeOfflineKey(name string, pub tmcrypto.PubKey, algo pubKeyType) (Info, error) { + info := newOfflineInfo(name, pub, algo) + err := ks.writeInfo(name, info) + if err != nil { + return nil, err + } + + return info, nil +} + +func (ks keystore) writeMultisigKey(name string, pub tmcrypto.PubKey) (Info, error) { + info := NewMultiInfo(name, pub) + err := ks.writeInfo(name, info) + if err != nil { + return nil, err + } + + return info, nil +} + +func addrHexKeyAsString(address sdk.Address) string { + return fmt.Sprintf("%s.%s", hex.EncodeToString(address.Bytes()), addressSuffix) } diff --git a/crypto/keyring/altkeyring_test.go b/crypto/keyring/keyring_test.go similarity index 100% rename from crypto/keyring/altkeyring_test.go rename to crypto/keyring/keyring_test.go diff --git a/crypto/keyring/signing_algorithms.go b/crypto/keyring/signing_algorithms.go index 5ddfb28d660..f82a892d41d 100644 --- a/crypto/keyring/signing_algorithms.go +++ b/crypto/keyring/signing_algorithms.go @@ -1,5 +1,11 @@ package keyring +import ( + "fmt" + + "github.com/tendermint/tendermint/crypto" +) + // pubKeyType defines an algorithm to derive key-pairs which can be used for cryptographic signing. type pubKeyType string @@ -24,3 +30,52 @@ func IsSupportedAlgorithm(supported []pubKeyType, algo pubKeyType) bool { } return false } + +type SigningAlgo interface { + Name() pubKeyType + DeriveKey() AltDeriveKeyFunc + PrivKeyGen() AltPrivKeyGenFunc +} + +type AltDeriveKeyFunc func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) +type AltPrivKeyGenFunc func(bz []byte) crypto.PrivKey + +func NewSigningAlgoFromString(str string) (SigningAlgo, error) { + if str != string(AltSecp256k1.Name()) { + return nil, fmt.Errorf("provided algorithm `%s` is not supported", str) + } + + return AltSecp256k1, nil +} + +type secp256k1Algo struct { +} + +func (s secp256k1Algo) Name() pubKeyType { + return Secp256k1 +} + +func (s secp256k1Algo) DeriveKey() AltDeriveKeyFunc { + return SecpDeriveKey +} + +func (s secp256k1Algo) PrivKeyGen() AltPrivKeyGenFunc { + return SecpPrivKeyGen +} + +var ( + // Secp256k1 uses the Bitcoin secp256k1 ECDSA parameters. + AltSecp256k1 = secp256k1Algo{} +) + +type AltSigningAlgoList []SigningAlgo + +func (l AltSigningAlgoList) Contains(algo SigningAlgo) bool { + for _, cAlgo := range l { + if cAlgo.Name() == algo.Name() { + return true + } + } + + return false +} diff --git a/crypto/keyring/alt_signing_algorithms_test.go b/crypto/keyring/signing_algorithms_test.go similarity index 97% rename from crypto/keyring/alt_signing_algorithms_test.go rename to crypto/keyring/signing_algorithms_test.go index ad9b09b7f7f..f0882c098e5 100644 --- a/crypto/keyring/alt_signing_algorithms_test.go +++ b/crypto/keyring/signing_algorithms_test.go @@ -14,7 +14,7 @@ func TestNewSigningAlgoByString(t *testing.T) { name string algoStr string isSupported bool - expectedAlgo AltSigningAlgo + expectedAlgo SigningAlgo expectedErr error }{ { diff --git a/x/auth/client/cli/tx_multisign.go b/x/auth/client/cli/tx_multisign.go index 83c068db182..e0d502a47f1 100644 --- a/x/auth/client/cli/tx_multisign.go +++ b/x/auth/client/cli/tx_multisign.go @@ -65,13 +65,13 @@ func makeMultiSignCmd(cdc *codec.Codec) func(cmd *cobra.Command, args []string) } inBuf := bufio.NewReader(cmd.InOrStdin()) - kb, err := keyring.NewKeyring(sdk.KeyringServiceName(), + kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), inBuf) if err != nil { return } - multisigInfo, err := kb.Get(args[1]) + multisigInfo, err := kb.Key(args[1]) if err != nil { return } diff --git a/x/genutil/client/cli/gentx.go b/x/genutil/client/cli/gentx.go index 6e2d7f73b60..1e138820de8 100644 --- a/x/genutil/client/cli/gentx.go +++ b/x/genutil/client/cli/gentx.go @@ -93,14 +93,14 @@ func GenTxCmd(ctx *server.Context, cdc *codec.Codec, mbm module.BasicManager, sm } inBuf := bufio.NewReader(cmd.InOrStdin()) - kb, err := keyring.NewKeyring(sdk.KeyringServiceName(), + kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flagClientHome), inBuf) if err != nil { return errors.Wrap(err, "failed to initialize keybase") } name := viper.GetString(flags.FlagName) - key, err := kb.Get(name) + key, err := kb.Key(name) if err != nil { return errors.Wrap(err, "failed to read from keybase") } From c974a9f233a6413cc4b2e7ef1aad8292766105c8 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 2 Apr 2020 23:27:02 +0200 Subject: [PATCH 106/148] Remove baseKeybase --- crypto/keyring/base_keybase.go | 181 --------------------------------- crypto/keyring/keyring.go | 33 ++++++ 2 files changed, 33 insertions(+), 181 deletions(-) diff --git a/crypto/keyring/base_keybase.go b/crypto/keyring/base_keybase.go index e1d5b300c68..2f6645b787f 100644 --- a/crypto/keyring/base_keybase.go +++ b/crypto/keyring/base_keybase.go @@ -1,57 +1,16 @@ package keyring import ( - "github.com/pkg/errors" - tmcrypto "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/secp256k1" - "github.com/cosmos/cosmos-sdk/crypto" "github.com/cosmos/cosmos-sdk/crypto/keys/hd" "github.com/cosmos/cosmos-sdk/types" bip39 "github.com/cosmos/go-bip39" ) -type ( - // baseKeybase is an auxiliary type that groups Keybase storage agnostic features - // together. - baseKeybase struct { - options kbOptions - } - - keyWriter interface { - writeLocalKeyer - infoWriter - } - - writeLocalKeyer interface { - writeLocalKey(name string, priv tmcrypto.PrivKey, algo pubKeyType) Info - } - - infoWriter interface { - writeInfo(name string, info Info) - } -) - var fundraiserPath = types.GetConfig().GetFullFundraiserPath() -// newBaseKeybase generates the base keybase with defaulting to tendermint SECP256K1 key type -func newBaseKeybase(optionsFns ...KeybaseOption) baseKeybase { - // Default options for keybase - options := kbOptions{ - keygenFunc: StdPrivKeyGen, - deriveFunc: StdDeriveKey, - supportedAlgos: []pubKeyType{Secp256k1}, - supportedAlgosLedger: []pubKeyType{Secp256k1}, - } - - for _, optionFn := range optionsFns { - optionFn(&options) - } - - return baseKeybase{options: options} -} - // StdPrivKeyGen is the default PrivKeyGen function in the keybase. // For now, it only supports Secp256k1 func StdPrivKeyGen(bz []byte, algo pubKeyType) (tmcrypto.PrivKey, error) { @@ -68,104 +27,6 @@ func SecpPrivKeyGen(bz []byte) tmcrypto.PrivKey { return secp256k1.PrivKeySecp256k1(bzArr) } -// CreateAccount creates an account Info object. -func (kb baseKeybase) CreateAccount( - keyWriter keyWriter, name, mnemonic, bip39Passphrase, encryptPasswd, hdPath string, algo pubKeyType, -) (Info, error) { - // create master key and derive first key for keyring - derivedPriv, err := kb.options.deriveFunc(mnemonic, bip39Passphrase, hdPath, algo) - if err != nil { - return nil, err - } - - privKey, err := kb.options.keygenFunc(derivedPriv, algo) - if err != nil { - return nil, err - } - - var info Info - - if encryptPasswd != "" { - info = keyWriter.writeLocalKey(name, privKey, algo) - } else { - info = kb.writeOfflineKey(keyWriter, name, privKey.PubKey(), algo) - } - - return info, nil -} - -// CreateLedger creates a new reference to a Ledger key pair. It returns a public -// key and a derivation path. It returns an error if the device could not be queried. -func (kb baseKeybase) CreateLedger( - w infoWriter, name string, algo pubKeyType, hrp string, account, index uint32, -) (Info, error) { - - if !IsSupportedAlgorithm(kb.SupportedAlgosLedger(), algo) { - return nil, ErrUnsupportedSigningAlgo - } - - coinType := types.GetConfig().GetCoinType() - hdPath := hd.NewFundraiserParams(account, coinType, index) - - priv, _, err := crypto.NewPrivKeyLedgerSecp256k1(*hdPath, hrp) - if err != nil { - return nil, err - } - - return kb.writeLedgerKey(w, name, priv.PubKey(), *hdPath, algo), nil -} - -// CreateMnemonic generates a new key with the given algorithm and language pair. -func (kb baseKeybase) CreateMnemonic( - keyWriter keyWriter, name string, language Language, passwd string, algo pubKeyType, -) (info Info, mnemonic string, err error) { - - if language != English { - return nil, "", ErrUnsupportedLanguage - } - - if !IsSupportedAlgorithm(kb.SupportedAlgos(), algo) { - return nil, "", ErrUnsupportedSigningAlgo - } - - // Default number of words (24): This generates a mnemonic directly from the - // number of words by reading system entropy. - entropy, err := bip39.NewEntropy(defaultEntropySize) - if err != nil { - return nil, "", err - } - - mnemonic, err = bip39.NewMnemonic(entropy) - if err != nil { - return nil, "", err - } - - info, err = kb.CreateAccount(keyWriter, name, mnemonic, DefaultBIP39Passphrase, passwd, fundraiserPath, algo) - if err != nil { - return nil, "", err - } - - return info, mnemonic, err -} - -func (kb baseKeybase) writeLedgerKey(w infoWriter, name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo pubKeyType) Info { - info := newLedgerInfo(name, pub, path, algo) - w.writeInfo(name, info) - return info -} - -func (kb baseKeybase) writeOfflineKey(w infoWriter, name string, pub tmcrypto.PubKey, algo pubKeyType) Info { - info := newOfflineInfo(name, pub, algo) - w.writeInfo(name, info) - return info -} - -func (kb baseKeybase) writeMultisigKey(w infoWriter, name string, pub tmcrypto.PubKey) Info { - info := NewMultiInfo(name, pub) - w.writeInfo(name, info) - return info -} - // StdDeriveKey is the default DeriveKey function in the keybase. // For now, it only supports Secp256k1 func StdDeriveKey(mnemonic string, bip39Passphrase, hdPath string, algo pubKeyType) ([]byte, error) { @@ -189,45 +50,3 @@ func SecpDeriveKey(mnemonic string, bip39Passphrase, hdPath string) ([]byte, err derivedKey, err := hd.DerivePrivateKeyForPath(masterPriv, ch, hdPath) return derivedKey[:], err } - -// CreateHDPath returns BIP 44 object from account and index parameters. -func CreateHDPath(account uint32, index uint32) *hd.BIP44Params { - return hd.NewFundraiserParams(account, types.GetConfig().GetCoinType(), index) -} - -// SupportedAlgos returns a list of supported signing algorithms. -func (kb baseKeybase) SupportedAlgos() []pubKeyType { - return kb.options.supportedAlgos -} - -// SupportedAlgosLedger returns a list of supported ledger signing algorithms. -func (kb baseKeybase) SupportedAlgosLedger() []pubKeyType { - return kb.options.supportedAlgosLedger -} - -// 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 tmcrypto.PubKey, err error) { - switch info.(type) { - case *ledgerInfo, ledgerInfo: - default: - return nil, nil, errors.New("not a ledger object") - } - path, err := info.GetPath() - if err != nil { - return - } - - priv, err := crypto.NewPrivKeyLedgerSecp256k1Unsafe(*path) - if err != nil { - return - } - - sig, err = priv.Sign(msg) - if err != nil { - return nil, nil, err - } - - return sig, priv.PubKey(), nil -} diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index aeb0347540b..d4f21b371c7 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -21,6 +21,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/input" "github.com/cosmos/cosmos-sdk/crypto" "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -513,6 +514,38 @@ func (ks keystore) Key(uid string) (Info, error) { return unmarshalInfo(bs.Data) } +// CreateHDPath returns BIP 44 object from account and index parameters. +func CreateHDPath(account uint32, index uint32) *hd.BIP44Params { + return hd.NewFundraiserParams(account, types.GetConfig().GetCoinType(), index) +} + +// 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 tmcrypto.PubKey, err error) { + switch info.(type) { + case *ledgerInfo, ledgerInfo: + default: + return nil, nil, errors.New("not a ledger object") + } + path, err := info.GetPath() + if err != nil { + return + } + + priv, err := crypto.NewPrivKeyLedgerSecp256k1Unsafe(*path) + if err != nil { + return + } + + sig, err = priv.Sign(msg) + if err != nil { + return nil, nil, err + } + + return sig, priv.PubKey(), nil +} + func lkbToKeyringConfig(appName, dir string, buf io.Reader, test bool) keyring.Config { if test { return keyring.Config{ From 412ba969109b3fd1c2abd1bc3cd8d251a892b421 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 2 Apr 2020 23:28:28 +0200 Subject: [PATCH 107/148] Make golangci-lint happy --- crypto/keyring/keyring_test.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 69483ecb4ec..4be3d1b76dd 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -1244,6 +1244,4 @@ func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetType(), mnemonic.GetType()) } -func accAddr(info Info) sdk.AccAddress { - return sdk.AccAddress(info.GetAddress()) -} +func accAddr(info Info) sdk.AccAddress { return info.GetAddress() } From 11934f796dda433b69b483827b6f878b7ca78d72 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 2 Apr 2020 23:36:08 +0200 Subject: [PATCH 108/148] Rename, cleanup --- crypto/keyring/keyring.go | 21 ++++-------- crypto/keyring/keyring_test.go | 4 +-- crypto/keyring/legacy.go | 40 ++++++++++++++++++++++- crypto/keyring/options.go | 40 +++-------------------- crypto/keyring/signing_algorithms.go | 26 +++++---------- crypto/keyring/signing_algorithms_test.go | 6 ++-- 6 files changed, 64 insertions(+), 73 deletions(-) diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index d4f21b371c7..9df21fe1263 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -109,12 +109,10 @@ type Exporter interface { ExportPrivKeyArmorByAddress(address sdk.Address, encryptPassphrase string) (armor string, err error) } -type AltKeyringOption func(options *altKrOptions) - // 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 ...AltKeyringOption) Keyring { +func NewInMemory(opts ...KeyringOption) Keyring { return newKeystore(keyring.NewArrayKeyring(nil), opts...) } @@ -122,7 +120,7 @@ func NewInMemory(opts ...AltKeyringOption) 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 ...AltKeyringOption, + appName, backend, rootDir string, userInput io.Reader, opts ...KeyringOption, ) (Keyring, error) { var db keyring.Keyring @@ -154,14 +152,14 @@ func New( type keystore struct { db keyring.Keyring - options altKrOptions + options keyringOptions } -func newKeystore(kr keyring.Keyring, opts ...AltKeyringOption) keystore { +func newKeystore(kr keyring.Keyring, opts ...KeyringOption) keystore { // Default options for keybase - options := altKrOptions{ - supportedAlgos: AltSigningAlgoList{AltSecp256k1}, - supportedAlgosLedger: AltSigningAlgoList{AltSecp256k1}, + options := keyringOptions{ + supportedAlgos: SigningAlgoList{AltSecp256k1}, + supportedAlgosLedger: SigningAlgoList{AltSecp256k1}, } for _, optionFn := range opts { @@ -354,11 +352,6 @@ func (ks keystore) writeLedgerKey(name string, pub tmcrypto.PubKey, path hd.BIP4 return info, nil } -type altKrOptions struct { - supportedAlgos AltSigningAlgoList - supportedAlgosLedger AltSigningAlgoList -} - func (ks keystore) SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) { return ks.writeMultisigKey(uid, pubkey) } diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 4be3d1b76dd..59545bd67f9 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -1224,8 +1224,8 @@ func TestAltKeyring_ConstructorSupportedAlgos(t *testing.T) { dir2, clean2 := tests.NewTestCaseDir(t) t.Cleanup(clean2) - keyring2, err := New(t.Name(), BackendTest, dir2, nil, func(options *altKrOptions) { - options.supportedAlgos = AltSigningAlgoList{ + keyring2, err := New(t.Name(), BackendTest, dir2, nil, func(options *keyringOptions) { + options.supportedAlgos = SigningAlgoList{ notSupportedAlgo{}, } }) diff --git a/crypto/keyring/legacy.go b/crypto/keyring/legacy.go index 13cd88ab67b..f1250bcf75a 100644 --- a/crypto/keyring/legacy.go +++ b/crypto/keyring/legacy.go @@ -196,7 +196,7 @@ type keyringMigrator struct { } func NewInfoImporter( - appName, backend, rootDir string, userInput io.Reader, opts ...AltKeyringOption, + appName, backend, rootDir string, userInput io.Reader, opts ...KeyringOption, ) (InfoImporter, error) { keyring, err := New(appName, backend, rootDir, userInput, opts...) if err != nil { @@ -224,3 +224,41 @@ func (m keyringMigrator) Import(uid string, armor string) error { return m.kr.writeInfo(uid, info) } + +// KeybaseOption overrides options for the db +type KeybaseOption func(*kbOptions) + +type kbOptions struct { + keygenFunc PrivKeyGenFunc + deriveFunc DeriveKeyFunc + supportedAlgos []pubKeyType + supportedAlgosLedger []pubKeyType +} + +// WithKeygenFunc applies an overridden key generation function to generate the private key. +func WithKeygenFunc(f PrivKeyGenFunc) KeybaseOption { + return func(o *kbOptions) { + o.keygenFunc = f + } +} + +// WithDeriveFunc applies an overridden key derivation function to generate the private key. +func WithDeriveFunc(f DeriveKeyFunc) KeybaseOption { + return func(o *kbOptions) { + o.deriveFunc = f + } +} + +// WithSupportedAlgos defines the list of accepted SigningAlgos. +func WithSupportedAlgos(algos []pubKeyType) KeybaseOption { + return func(o *kbOptions) { + o.supportedAlgos = algos + } +} + +// WithSupportedAlgosLedger defines the list of accepted SigningAlgos compatible with Ledger. +func WithSupportedAlgosLedger(algos []pubKeyType) KeybaseOption { + return func(o *kbOptions) { + o.supportedAlgosLedger = algos + } +} diff --git a/crypto/keyring/options.go b/crypto/keyring/options.go index b7ad9903102..09ee9a1d9cf 100644 --- a/crypto/keyring/options.go +++ b/crypto/keyring/options.go @@ -1,39 +1,9 @@ package keyring -// KeybaseOption overrides options for the db -type KeybaseOption func(*kbOptions) +// KeyringOption overrides keyring configuratoin options. +type KeyringOption func(options *keyringOptions) -type kbOptions struct { - keygenFunc PrivKeyGenFunc - deriveFunc DeriveKeyFunc - supportedAlgos []pubKeyType - supportedAlgosLedger []pubKeyType -} - -// WithKeygenFunc applies an overridden key generation function to generate the private key. -func WithKeygenFunc(f PrivKeyGenFunc) KeybaseOption { - return func(o *kbOptions) { - o.keygenFunc = f - } -} - -// WithDeriveFunc applies an overridden key derivation function to generate the private key. -func WithDeriveFunc(f DeriveKeyFunc) KeybaseOption { - return func(o *kbOptions) { - o.deriveFunc = f - } -} - -// WithSupportedAlgos defines the list of accepted SigningAlgos. -func WithSupportedAlgos(algos []pubKeyType) KeybaseOption { - return func(o *kbOptions) { - o.supportedAlgos = algos - } -} - -// WithSupportedAlgosLedger defines the list of accepted SigningAlgos compatible with Ledger. -func WithSupportedAlgosLedger(algos []pubKeyType) KeybaseOption { - return func(o *kbOptions) { - o.supportedAlgosLedger = algos - } +type keyringOptions struct { + supportedAlgos SigningAlgoList + supportedAlgosLedger SigningAlgoList } diff --git a/crypto/keyring/signing_algorithms.go b/crypto/keyring/signing_algorithms.go index f82a892d41d..f539c290132 100644 --- a/crypto/keyring/signing_algorithms.go +++ b/crypto/keyring/signing_algorithms.go @@ -21,24 +21,14 @@ const ( Sr25519 = pubKeyType("sr25519") ) -// IsSupportedAlgorithm returns whether the signing algorithm is in the passed-in list of supported algorithms. -func IsSupportedAlgorithm(supported []pubKeyType, algo pubKeyType) bool { - for _, supportedAlgo := range supported { - if algo == supportedAlgo { - return true - } - } - return false -} - type SigningAlgo interface { Name() pubKeyType - DeriveKey() AltDeriveKeyFunc - PrivKeyGen() AltPrivKeyGenFunc + DeriveKey() DeriveKeyFn + PrivKeyGen() PrivKeyGenFn } -type AltDeriveKeyFunc func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) -type AltPrivKeyGenFunc func(bz []byte) crypto.PrivKey +type DeriveKeyFn func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) +type PrivKeyGenFn func(bz []byte) crypto.PrivKey func NewSigningAlgoFromString(str string) (SigningAlgo, error) { if str != string(AltSecp256k1.Name()) { @@ -55,11 +45,11 @@ func (s secp256k1Algo) Name() pubKeyType { return Secp256k1 } -func (s secp256k1Algo) DeriveKey() AltDeriveKeyFunc { +func (s secp256k1Algo) DeriveKey() DeriveKeyFn { return SecpDeriveKey } -func (s secp256k1Algo) PrivKeyGen() AltPrivKeyGenFunc { +func (s secp256k1Algo) PrivKeyGen() PrivKeyGenFn { return SecpPrivKeyGen } @@ -68,9 +58,9 @@ var ( AltSecp256k1 = secp256k1Algo{} ) -type AltSigningAlgoList []SigningAlgo +type SigningAlgoList []SigningAlgo -func (l AltSigningAlgoList) Contains(algo SigningAlgo) bool { +func (l SigningAlgoList) Contains(algo SigningAlgo) bool { for _, cAlgo := range l { if cAlgo.Name() == algo.Name() { return true diff --git a/crypto/keyring/signing_algorithms_test.go b/crypto/keyring/signing_algorithms_test.go index f0882c098e5..d6375e131fe 100644 --- a/crypto/keyring/signing_algorithms_test.go +++ b/crypto/keyring/signing_algorithms_test.go @@ -46,7 +46,7 @@ func TestNewSigningAlgoByString(t *testing.T) { } func TestAltSigningAlgoList_Contains(t *testing.T) { - list := AltSigningAlgoList{ + list := SigningAlgoList{ AltSecp256k1, } @@ -61,10 +61,10 @@ func (n notSupportedAlgo) Name() pubKeyType { return "notSupported" } -func (n notSupportedAlgo) DeriveKey() AltDeriveKeyFunc { +func (n notSupportedAlgo) DeriveKey() DeriveKeyFn { return SecpDeriveKey } -func (n notSupportedAlgo) PrivKeyGen() AltPrivKeyGenFunc { +func (n notSupportedAlgo) PrivKeyGen() PrivKeyGenFn { return SecpPrivKeyGen } From cd85d7c519cb91052ad876c86810d1660e98845a Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Thu, 2 Apr 2020 23:48:19 +0200 Subject: [PATCH 109/148] Cleanup --- crypto/keyring/keyring.go | 8 ++++++++ crypto/keyring/keyring_test.go | 5 +++++ crypto/keyring/options.go | 9 --------- 3 files changed, 13 insertions(+), 9 deletions(-) delete mode 100644 crypto/keyring/options.go diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 9df21fe1263..cba37caf683 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -507,6 +507,14 @@ func (ks keystore) Key(uid string) (Info, error) { return unmarshalInfo(bs.Data) } +// KeyringOption overrides keyring configuratoin options. +type KeyringOption func(options *keyringOptions) + +type keyringOptions struct { + supportedAlgos SigningAlgoList + supportedAlgosLedger SigningAlgoList +} + // CreateHDPath returns BIP 44 object from account and index parameters. func CreateHDPath(account uint32, index uint32) *hd.BIP44Params { return hd.NewFundraiserParams(account, types.GetConfig().GetCoinType(), index) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 59545bd67f9..9be0dd169a0 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -36,6 +36,11 @@ func TestNewKeyring(t *testing.T) { kr, err := New("cosmos", BackendFile, dir, mockIn) require.NoError(t, err) + nilKr, err := New("cosmos", "fuzzy", dir, mockIn) + require.Error(t, err) + require.Nil(t, nilKr) + require.Equal(t, "unknown keyring backend fuzzy", err.Error()) + mockIn.Reset("password\npassword\n") info, _, err := kr.NewMnemonic("foo", English, AltSecp256k1) require.NoError(t, err) diff --git a/crypto/keyring/options.go b/crypto/keyring/options.go deleted file mode 100644 index 09ee9a1d9cf..00000000000 --- a/crypto/keyring/options.go +++ /dev/null @@ -1,9 +0,0 @@ -package keyring - -// KeyringOption overrides keyring configuratoin options. -type KeyringOption func(options *keyringOptions) - -type keyringOptions struct { - supportedAlgos SigningAlgoList - supportedAlgosLedger SigningAlgoList -} From 2af9073c685604c42fef62ed209bd4b6d41c3892 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 3 Apr 2020 00:02:35 +0200 Subject: [PATCH 110/148] Tidy up --- crypto/keyring/base_keybase.go | 52 ----------------------- crypto/keyring/keyring.go | 24 +++++------ crypto/keyring/legacy.go | 2 +- crypto/keyring/signing_algorithms.go | 45 ++++++++++++++++---- crypto/keyring/signing_algorithms_test.go | 6 +-- 5 files changed, 52 insertions(+), 77 deletions(-) delete mode 100644 crypto/keyring/base_keybase.go diff --git a/crypto/keyring/base_keybase.go b/crypto/keyring/base_keybase.go deleted file mode 100644 index 2f6645b787f..00000000000 --- a/crypto/keyring/base_keybase.go +++ /dev/null @@ -1,52 +0,0 @@ -package keyring - -import ( - tmcrypto "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/crypto/secp256k1" - - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" - "github.com/cosmos/cosmos-sdk/types" - bip39 "github.com/cosmos/go-bip39" -) - -var fundraiserPath = types.GetConfig().GetFullFundraiserPath() - -// StdPrivKeyGen is the default PrivKeyGen function in the keybase. -// For now, it only supports Secp256k1 -func StdPrivKeyGen(bz []byte, algo pubKeyType) (tmcrypto.PrivKey, error) { - if algo == Secp256k1 { - return SecpPrivKeyGen(bz), nil - } - return nil, ErrUnsupportedSigningAlgo -} - -// SecpPrivKeyGen generates a secp256k1 private key from the given bytes -func SecpPrivKeyGen(bz []byte) tmcrypto.PrivKey { - var bzArr [32]byte - copy(bzArr[:], bz) - return secp256k1.PrivKeySecp256k1(bzArr) -} - -// StdDeriveKey is the default DeriveKey function in the keybase. -// For now, it only supports Secp256k1 -func StdDeriveKey(mnemonic string, bip39Passphrase, hdPath string, algo pubKeyType) ([]byte, error) { - if algo == Secp256k1 { - return SecpDeriveKey(mnemonic, bip39Passphrase, hdPath) - } - return nil, ErrUnsupportedSigningAlgo -} - -// SecpDeriveKey derives and returns the secp256k1 private key for the given seed and HD path. -func SecpDeriveKey(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) { - seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase) - if err != nil { - return nil, err - } - - masterPriv, ch := hd.ComputeMastersFromSeed(seed) - if len(hdPath) == 0 { - return masterPriv[:], nil - } - derivedKey, err := hd.DerivePrivateKeyForPath(masterPriv, ch, hdPath) - return derivedKey[:], err -} diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index cba37caf683..b7ee68ba93b 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -63,13 +63,13 @@ type Keyring interface { // key from that, and persists it to the storage. Returns the generated mnemonic and the key // Info. It returns an error if it fails to generate a key for the given algo type, or if // another key is already stored under the same name. - NewMnemonic(uid string, language Language, algo SigningAlgo) (Info, string, error) + NewMnemonic(uid string, language Language, algo SignatureAlgo) (Info, string, error) // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. - NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SigningAlgo) (Info, error) + NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SignatureAlgo) (Info, error) // SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. - SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) + SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, account, index uint32) (Info, error) // SavePubKey stores a public key and returns the persisted Info structure. SavePubKey(uid string, pubkey tmcrypto.PubKey, algo pubKeyType) (Info, error) @@ -112,7 +112,7 @@ type Exporter interface { // 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 ...KeyringOption) Keyring { +func NewInMemory(opts ...Option) Keyring { return newKeystore(keyring.NewArrayKeyring(nil), opts...) } @@ -120,7 +120,7 @@ func NewInMemory(opts ...KeyringOption) 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 ...KeyringOption, + appName, backend, rootDir string, userInput io.Reader, opts ...Option, ) (Keyring, error) { var db keyring.Keyring @@ -155,7 +155,7 @@ type keystore struct { options keyringOptions } -func newKeystore(kr keyring.Keyring, opts ...KeyringOption) keystore { +func newKeystore(kr keyring.Keyring, opts ...Option) keystore { // Default options for keybase options := keyringOptions{ supportedAlgos: SigningAlgoList{AltSecp256k1}, @@ -326,7 +326,7 @@ func (ks keystore) SignByAddress(address sdk.Address, msg []byte) ([]byte, tmcry return ks.Sign(key.GetName(), msg) } -func (ks keystore) SaveLedgerKey(uid string, algo SigningAlgo, hrp string, account, index uint32) (Info, error) { +func (ks keystore) SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, account, index uint32) (Info, error) { if !ks.options.supportedAlgosLedger.Contains(algo) { return nil, ErrUnsupportedSigningAlgo } @@ -443,7 +443,7 @@ func (ks keystore) List() ([]Info, error) { return res, nil } -func (ks keystore) NewMnemonic(uid string, language Language, algo SigningAlgo) (Info, string, error) { +func (ks keystore) NewMnemonic(uid string, language Language, algo SignatureAlgo) (Info, string, error) { if language != English { return nil, "", ErrUnsupportedLanguage } @@ -472,7 +472,7 @@ func (ks keystore) NewMnemonic(uid string, language Language, algo SigningAlgo) return info, mnemonic, err } -func (ks keystore) NewAccount(uid string, mnemonic string, bip39Passphrase string, hdPath string, algo SigningAlgo) (Info, error) { +func (ks keystore) NewAccount(uid string, mnemonic string, bip39Passphrase string, hdPath string, algo SignatureAlgo) (Info, error) { if !ks.isSupportedSigningAlgo(algo) { return nil, ErrUnsupportedSigningAlgo } @@ -488,7 +488,7 @@ func (ks keystore) NewAccount(uid string, mnemonic string, bip39Passphrase strin return ks.writeLocalKey(uid, privKey, algo.Name()) } -func (ks keystore) isSupportedSigningAlgo(algo SigningAlgo) bool { +func (ks keystore) isSupportedSigningAlgo(algo SignatureAlgo) bool { return ks.options.supportedAlgos.Contains(algo) } @@ -507,8 +507,8 @@ func (ks keystore) Key(uid string) (Info, error) { return unmarshalInfo(bs.Data) } -// KeyringOption overrides keyring configuratoin options. -type KeyringOption func(options *keyringOptions) +// Option overrides keyring configuration options. +type Option func(options *keyringOptions) type keyringOptions struct { supportedAlgos SigningAlgoList diff --git a/crypto/keyring/legacy.go b/crypto/keyring/legacy.go index f1250bcf75a..ca4f35cbe5f 100644 --- a/crypto/keyring/legacy.go +++ b/crypto/keyring/legacy.go @@ -196,7 +196,7 @@ type keyringMigrator struct { } func NewInfoImporter( - appName, backend, rootDir string, userInput io.Reader, opts ...KeyringOption, + appName, backend, rootDir string, userInput io.Reader, opts ...Option, ) (InfoImporter, error) { keyring, err := New(appName, backend, rootDir, userInput, opts...) if err != nil { diff --git a/crypto/keyring/signing_algorithms.go b/crypto/keyring/signing_algorithms.go index f539c290132..d614404b937 100644 --- a/crypto/keyring/signing_algorithms.go +++ b/crypto/keyring/signing_algorithms.go @@ -3,7 +3,12 @@ package keyring import ( "fmt" + "github.com/cosmos/go-bip39" "github.com/tendermint/tendermint/crypto" + tmcrypto "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/secp256k1" + + "github.com/cosmos/cosmos-sdk/crypto/keys/hd" ) // pubKeyType defines an algorithm to derive key-pairs which can be used for cryptographic signing. @@ -21,16 +26,13 @@ const ( Sr25519 = pubKeyType("sr25519") ) -type SigningAlgo interface { +type SignatureAlgo interface { Name() pubKeyType DeriveKey() DeriveKeyFn PrivKeyGen() PrivKeyGenFn } -type DeriveKeyFn func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) -type PrivKeyGenFn func(bz []byte) crypto.PrivKey - -func NewSigningAlgoFromString(str string) (SigningAlgo, error) { +func NewSigningAlgoFromString(str string) (SignatureAlgo, error) { if str != string(AltSecp256k1.Name()) { return nil, fmt.Errorf("provided algorithm `%s` is not supported", str) } @@ -46,11 +48,11 @@ func (s secp256k1Algo) Name() pubKeyType { } func (s secp256k1Algo) DeriveKey() DeriveKeyFn { - return SecpDeriveKey + return Secp256k1DeriveKey } func (s secp256k1Algo) PrivKeyGen() PrivKeyGenFn { - return SecpPrivKeyGen + return Secp256k1PrivKeyGen } var ( @@ -58,9 +60,9 @@ var ( AltSecp256k1 = secp256k1Algo{} ) -type SigningAlgoList []SigningAlgo +type SigningAlgoList []SignatureAlgo -func (l SigningAlgoList) Contains(algo SigningAlgo) bool { +func (l SigningAlgoList) Contains(algo SignatureAlgo) bool { for _, cAlgo := range l { if cAlgo.Name() == algo.Name() { return true @@ -69,3 +71,28 @@ func (l SigningAlgoList) Contains(algo SigningAlgo) bool { return false } + +// Secp256k1PrivKeyGen generates a secp256k1 private key from the given bytes +func Secp256k1PrivKeyGen(bz []byte) tmcrypto.PrivKey { + var bzArr [32]byte + copy(bzArr[:], bz) + return secp256k1.PrivKeySecp256k1(bzArr) +} + +// Secp256k1DeriveKey derives and returns the secp256k1 private key for the given seed and HD path. +func Secp256k1DeriveKey(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) { + seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase) + if err != nil { + return nil, err + } + + masterPriv, ch := hd.ComputeMastersFromSeed(seed) + if len(hdPath) == 0 { + return masterPriv[:], nil + } + derivedKey, err := hd.DerivePrivateKeyForPath(masterPriv, ch, hdPath) + return derivedKey[:], err +} + +type DeriveKeyFn func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) +type PrivKeyGenFn func(bz []byte) crypto.PrivKey diff --git a/crypto/keyring/signing_algorithms_test.go b/crypto/keyring/signing_algorithms_test.go index d6375e131fe..d84edb03149 100644 --- a/crypto/keyring/signing_algorithms_test.go +++ b/crypto/keyring/signing_algorithms_test.go @@ -14,7 +14,7 @@ func TestNewSigningAlgoByString(t *testing.T) { name string algoStr string isSupported bool - expectedAlgo SigningAlgo + expectedAlgo SignatureAlgo expectedErr error }{ { @@ -62,9 +62,9 @@ func (n notSupportedAlgo) Name() pubKeyType { } func (n notSupportedAlgo) DeriveKey() DeriveKeyFn { - return SecpDeriveKey + return Secp256k1DeriveKey } func (n notSupportedAlgo) PrivKeyGen() PrivKeyGenFn { - return SecpPrivKeyGen + return Secp256k1PrivKeyGen } From dcb05aef41685036aabb0ffd88ffb27f2638fdba Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 3 Apr 2020 00:14:44 +0200 Subject: [PATCH 111/148] Tidy up, more tests --- crypto/keyring/legacy.go | 28 ----------------------- crypto/keyring/legacy_test.go | 11 +++++++++ crypto/keyring/signing_algorithms_test.go | 7 ++++++ 3 files changed, 18 insertions(+), 28 deletions(-) diff --git a/crypto/keyring/legacy.go b/crypto/keyring/legacy.go index ca4f35cbe5f..4ba99d82eb8 100644 --- a/crypto/keyring/legacy.go +++ b/crypto/keyring/legacy.go @@ -234,31 +234,3 @@ type kbOptions struct { supportedAlgos []pubKeyType supportedAlgosLedger []pubKeyType } - -// WithKeygenFunc applies an overridden key generation function to generate the private key. -func WithKeygenFunc(f PrivKeyGenFunc) KeybaseOption { - return func(o *kbOptions) { - o.keygenFunc = f - } -} - -// WithDeriveFunc applies an overridden key derivation function to generate the private key. -func WithDeriveFunc(f DeriveKeyFunc) KeybaseOption { - return func(o *kbOptions) { - o.deriveFunc = f - } -} - -// WithSupportedAlgos defines the list of accepted SigningAlgos. -func WithSupportedAlgos(algos []pubKeyType) KeybaseOption { - return func(o *kbOptions) { - o.supportedAlgos = algos - } -} - -// WithSupportedAlgosLedger defines the list of accepted SigningAlgos compatible with Ledger. -func WithSupportedAlgosLedger(algos []pubKeyType) KeybaseOption { - return func(o *kbOptions) { - o.supportedAlgosLedger = algos - } -} diff --git a/crypto/keyring/legacy_test.go b/crypto/keyring/legacy_test.go index 5a7ef869e0b..9be4a8ca6ba 100644 --- a/crypto/keyring/legacy_test.go +++ b/crypto/keyring/legacy_test.go @@ -1,6 +1,7 @@ package keyring_test import ( + "io" "path/filepath" "testing" @@ -38,11 +39,21 @@ func TestLegacyKeybase(t *testing.T) { 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) importer, err := keyring.NewInfoImporter("cosmos", "memory", "", nil) require.NoError(t, err) + err = importer.Import("test", "") + require.Error(t, err) + require.Equal(t, io.EOF, err) require.NoError(t, importer.Import("test", armoredInfo)) + + err = importer.Import("test", armoredInfo) + require.Error(t, err) + require.Equal(t, `cannot overwrite key "test"`, err.Error()) } diff --git a/crypto/keyring/signing_algorithms_test.go b/crypto/keyring/signing_algorithms_test.go index d84edb03149..920323920ce 100644 --- a/crypto/keyring/signing_algorithms_test.go +++ b/crypto/keyring/signing_algorithms_test.go @@ -9,6 +9,13 @@ import ( "github.com/stretchr/testify/assert" ) +func TestDefaults(t *testing.T) { + require.Equal(t, pubKeyType("multi"), MultiAlgo) + require.Equal(t, pubKeyType("secp256k1"), Secp256k1) + require.Equal(t, pubKeyType("ed25519"), Ed25519) + require.Equal(t, pubKeyType("sr25519"), Sr25519) +} + func TestNewSigningAlgoByString(t *testing.T) { tests := []struct { name string From fd7ca14bf9da9715cc8d592d6be9ba309b05f581 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 3 Apr 2020 00:39:21 +0200 Subject: [PATCH 112/148] temporarily fix singleton --- crypto/keyring/keyring.go | 10 ++++++---- crypto/keyring/keyring_test.go | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index b7ee68ba93b..c48f3631f7e 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -21,7 +21,6 @@ import ( "github.com/cosmos/cosmos-sdk/client/input" "github.com/cosmos/cosmos-sdk/crypto" "github.com/cosmos/cosmos-sdk/crypto/keys/hd" - "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -44,6 +43,9 @@ const ( var ( _ Keyring = &keystore{} maxPassphraseEntryAttempts = 3 + + // TODO: remove and add to methods parameters + config = sdk.GetConfig() ) // Keyring exposes operations over a backend supported by github.com/99designs/keyring. @@ -331,7 +333,7 @@ func (ks keystore) SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, acc return nil, ErrUnsupportedSigningAlgo } - coinType := sdk.GetConfig().GetCoinType() + coinType := config.GetCoinType() hdPath := hd.NewFundraiserParams(account, coinType, index) priv, _, err := crypto.NewPrivKeyLedgerSecp256k1(*hdPath, hrp) @@ -464,7 +466,7 @@ func (ks keystore) NewMnemonic(uid string, language Language, algo SignatureAlgo return nil, "", err } - info, err := ks.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.GetConfig().GetFullFundraiserPath(), algo) + info, err := ks.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, config.GetFullFundraiserPath(), algo) if err != nil { return nil, "", err } @@ -517,7 +519,7 @@ type keyringOptions struct { // CreateHDPath returns BIP 44 object from account and index parameters. func CreateHDPath(account uint32, index uint32) *hd.BIP44Params { - return hd.NewFundraiserParams(account, types.GetConfig().GetCoinType(), index) + return hd.NewFundraiserParams(account, config.GetCoinType(), index) } // SignWithLedger signs a binary message with the ledger device referenced by an Info object diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 9be0dd169a0..db0f4ff06c7 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -888,10 +888,10 @@ func TestAltKeyring_NewAccount(t *testing.T) { uid := "newUid" // Fails on creating unsupported pubKeyType - _, err = keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.GetConfig().GetFullFundraiserPath(), notSupportedAlgo{}) + _, err = keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, config.GetFullFundraiserPath(), notSupportedAlgo{}) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) - info, err := keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.GetConfig().GetFullFundraiserPath(), AltSecp256k1) + info, err := keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, config.GetFullFundraiserPath(), AltSecp256k1) require.NoError(t, err) require.Equal(t, uid, info.GetName()) From 1a1717b2083772904eb3ccecef0a0901c4748f80 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 3 Apr 2020 00:41:21 +0200 Subject: [PATCH 113/148] remove unused members --- crypto/keyring/legacy.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crypto/keyring/legacy.go b/crypto/keyring/legacy.go index 4ba99d82eb8..29766c16bc0 100644 --- a/crypto/keyring/legacy.go +++ b/crypto/keyring/legacy.go @@ -225,12 +225,8 @@ func (m keyringMigrator) Import(uid string, armor string) error { return m.kr.writeInfo(uid, info) } -// KeybaseOption overrides options for the db +// KeybaseOption overrides options for the db. type KeybaseOption func(*kbOptions) type kbOptions struct { - keygenFunc PrivKeyGenFunc - deriveFunc DeriveKeyFunc - supportedAlgos []pubKeyType - supportedAlgosLedger []pubKeyType } From b37a2f7af8ac36a37a1593b16a499d8bddf993bd Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 3 Apr 2020 00:58:44 +0200 Subject: [PATCH 114/148] Try remove config singleton --- client/keys/add.go | 8 ++++++-- crypto/keyring/keyring.go | 10 ++-------- crypto/keyring/keyring_test.go | 10 +++++----- crypto/keys/hd/fundraiser_test.go | 4 ++++ crypto/keys/hd/hdpath.go | 6 +++++- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/client/keys/add.go b/client/keys/add.go index 56a6d0d44ed..23ce9118a15 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -13,6 +13,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/input" "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/crypto/keys/hd" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/spf13/cobra" @@ -27,6 +28,7 @@ const ( flagInteractive = "interactive" flagRecover = "recover" flagNoBackup = "no-backup" + flagCoinType = "coin-type" flagAccount = "account" flagIndex = "index" flagMultisig = "multisig" @@ -73,6 +75,7 @@ the flag --nosort is set. cmd.Flags().Bool(flagNoBackup, false, "Don't print out seed phrase (if others are watching the terminal)") cmd.Flags().Bool(flags.FlagDryRun, false, "Perform action, but don't add key to local keystore") cmd.Flags().String(flagHDPath, "", "Manual HD Path derivation (overrides BIP44 config)") + cmd.Flags().Uint32(flagCoinType, sdk.CoinType, "coin type number for HD derivation") cmd.Flags().Uint32(flagAccount, 0, "Account number for HD derivation") cmd.Flags().Uint32(flagIndex, 0, "Address index number for HD derivation") cmd.Flags().Bool(flags.FlagIndentResponse, false, "Add indent to JSON response") @@ -179,6 +182,7 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *buf return nil } + coinType := uint32(viper.GetInt(flagCoinType)) account := uint32(viper.GetInt(flagAccount)) index := uint32(viper.GetInt(flagIndex)) @@ -186,7 +190,7 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *buf var hdPath string if useBIP44 { - hdPath = keyring.CreateHDPath(account, index).String() + hdPath = hd.CreateHDPath(coinType, account, index).String() } else { hdPath = viper.GetString(flagHDPath) } @@ -199,7 +203,7 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *buf } bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix() - info, err := kb.SaveLedgerKey(name, keyring.AltSecp256k1, bech32PrefixAccAddr, account, index) + info, err := kb.SaveLedgerKey(name, keyring.AltSecp256k1, bech32PrefixAccAddr, account, coinType, index) if err != nil { return err } diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index c48f3631f7e..25e0d68c943 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -71,7 +71,7 @@ type Keyring interface { NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SignatureAlgo) (Info, error) // SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. - SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, account, index uint32) (Info, error) + SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, account, coinType, index uint32) (Info, error) // SavePubKey stores a public key and returns the persisted Info structure. SavePubKey(uid string, pubkey tmcrypto.PubKey, algo pubKeyType) (Info, error) @@ -328,12 +328,11 @@ func (ks keystore) SignByAddress(address sdk.Address, msg []byte) ([]byte, tmcry return ks.Sign(key.GetName(), msg) } -func (ks keystore) SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, account, index uint32) (Info, error) { +func (ks keystore) SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, account, coinType, index uint32) (Info, error) { if !ks.options.supportedAlgosLedger.Contains(algo) { return nil, ErrUnsupportedSigningAlgo } - coinType := config.GetCoinType() hdPath := hd.NewFundraiserParams(account, coinType, index) priv, _, err := crypto.NewPrivKeyLedgerSecp256k1(*hdPath, hrp) @@ -517,11 +516,6 @@ type keyringOptions struct { supportedAlgosLedger SigningAlgoList } -// CreateHDPath returns BIP 44 object from account and index parameters. -func CreateHDPath(account uint32, index uint32) *hd.BIP44Params { - return hd.NewFundraiserParams(account, config.GetCoinType(), index) -} - // 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. diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index db0f4ff06c7..0583bcd14ae 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -137,7 +137,7 @@ func TestSignVerifyKeyRingWithLedger(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - i1, err := kb.SaveLedgerKey("key", AltSecp256k1, "cosmos", 0, 0) + i1, err := kb.SaveLedgerKey("key", AltSecp256k1, "cosmos", 0, 118, 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") @@ -431,7 +431,7 @@ func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { _, err := kb.NewAccount( "some_account", "malarkey pair crucial catch public canyon evil outer stage ten gym tornado", - "", CreateHDPath(0, 0).String(), AltSecp256k1) + "", hd.CreateHDPath(118, 0, 0).String(), AltSecp256k1) require.Error(t, err) require.Equal(t, "Invalid mnemonic", err.Error()) } @@ -439,7 +439,7 @@ func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { func TestInMemoryCreateLedger(t *testing.T) { kb := NewInMemory() - ledger, err := kb.SaveLedgerKey("some_account", AltSecp256k1, "cosmos", 3, 1) + ledger, err := kb.SaveLedgerKey("some_account", AltSecp256k1, "cosmos", 3, 118, 1) if err != nil { require.Error(t, err) @@ -909,10 +909,10 @@ func TestAltKeyring_SaveLedgerKey(t *testing.T) { require.NoError(t, err) // Test unsupported Algo - _, err = keyring.SaveLedgerKey("key", notSupportedAlgo{}, "cosmos", 0, 0) + _, err = keyring.SaveLedgerKey("key", notSupportedAlgo{}, "cosmos", 0, 118, 0) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) - ledger, err := keyring.SaveLedgerKey("some_account", AltSecp256k1, "cosmos", 3, 1) + ledger, err := keyring.SaveLedgerKey("some_account", AltSecp256k1, "cosmos", 3, 118, 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") diff --git a/crypto/keys/hd/fundraiser_test.go b/crypto/keys/hd/fundraiser_test.go index 6fa4ca725f0..02671a869f9 100644 --- a/crypto/keys/hd/fundraiser_test.go +++ b/crypto/keys/hd/fundraiser_test.go @@ -24,6 +24,10 @@ type addrData struct { Addr string } +func TestFullFundraiserPath(t *testing.T) { + require.Equal(t, "44'/118'/0'/0/0", NewFundraiserParams(0, 118, 0).String()) +} + func initFundraiserTestVectors(t *testing.T) []addrData { // NOTE: atom fundraiser address // var hdPath string = "m/44'/118'/0'/0/0" diff --git a/crypto/keys/hd/hdpath.go b/crypto/keys/hd/hdpath.go index a92d79be1f2..cadb3635ae1 100644 --- a/crypto/keys/hd/hdpath.go +++ b/crypto/keys/hd/hdpath.go @@ -14,7 +14,6 @@ package hd import ( "crypto/hmac" "crypto/sha512" - "encoding/binary" "errors" "fmt" @@ -255,3 +254,8 @@ func i64(key []byte, data []byte) (il [32]byte, ir [32]byte) { return } + +// CreateHDPath returns BIP 44 object from account and index parameters. +func CreateHDPath(coinType, account, index uint32) *BIP44Params { + return NewFundraiserParams(account, coinType, index) +} From 6a2a1f54b203254ce74b6547a272a53f3953a731 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 3 Apr 2020 01:18:16 +0200 Subject: [PATCH 115/148] Fix race condition, remove config from keyring --- client/keys/add.go | 2 +- client/keys/add_ledger_test.go | 4 ++ client/keys/delete_test.go | 2 +- client/keys/root_test.go | 2 + client/keys/show_test.go | 2 +- crypto/armor_test.go | 3 +- crypto/keyring/keyring.go | 13 ++--- crypto/keyring/keyring_test.go | 103 +++++++++++++++++---------------- server/init.go | 5 +- 9 files changed, 71 insertions(+), 65 deletions(-) diff --git a/client/keys/add.go b/client/keys/add.go index 23ce9118a15..afbcc030092 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -203,7 +203,7 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *buf } bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix() - info, err := kb.SaveLedgerKey(name, keyring.AltSecp256k1, bech32PrefixAccAddr, account, coinType, index) + info, err := kb.SaveLedgerKey(name, keyring.AltSecp256k1, bech32PrefixAccAddr, coinType, account, index) if err != nil { return err } diff --git a/client/keys/add_ledger_test.go b/client/keys/add_ledger_test.go index de2920f51e0..f8be693938a 100644 --- a/client/keys/add_ledger_test.go +++ b/client/keys/add_ledger_test.go @@ -41,6 +41,9 @@ func Test_runAddCmdLedgerWithCustomCoinType(t *testing.T) { t.Cleanup(kbCleanUp) viper.Set(flags.FlagHome, kbHome) viper.Set(flags.FlagUseLedger, true) + viper.Set(flagAccount, "0") + viper.Set(flagIndex, "0") + viper.Set(flagCoinType, "330") /// Test Text viper.Set(cli.OutputFlag, OutputFormatText) @@ -90,6 +93,7 @@ func Test_runAddCmdLedger(t *testing.T) { viper.Set(cli.OutputFlag, OutputFormatText) // Now enter password mockIn.Reset("test1234\ntest1234\n") + viper.Set(flagCoinType, sdk.CoinType) require.NoError(t, runAddCmd(cmd, []string{"keyname1"})) // Now check that it has been stored properly diff --git a/client/keys/delete_test.go b/client/keys/delete_test.go index e305b89e129..4f741c8853d 100644 --- a/client/keys/delete_test.go +++ b/client/keys/delete_test.go @@ -36,7 +36,7 @@ func Test_runDeleteCmd(t *testing.T) { require.NoError(t, err) _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, keyring.AltSecp256k1) require.NoError(t, err) - _, _, err = kb.NewMnemonic(fakeKeyName2, keyring.English, keyring.AltSecp256k1) + _, _, err = kb.NewMnemonic(fakeKeyName2, keyring.English, sdk.FullFundraiserPath, keyring.AltSecp256k1) require.NoError(t, err) err = runDeleteCmd(deleteKeyCommand, []string{"blah"}) diff --git a/client/keys/root_test.go b/client/keys/root_test.go index 29fbe145504..e995da9796d 100644 --- a/client/keys/root_test.go +++ b/client/keys/root_test.go @@ -9,6 +9,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/keyring" + sdk "github.com/cosmos/cosmos-sdk/types" ) func TestCommands(t *testing.T) { @@ -21,5 +22,6 @@ func TestCommands(t *testing.T) { func TestMain(m *testing.M) { viper.Set(flags.FlagKeyringBackend, keyring.BackendTest) + viper.Set(flagCoinType, sdk.CoinType) os.Exit(m.Run()) } diff --git a/client/keys/show_test.go b/client/keys/show_test.go index 4da7057aa90..210c7590531 100644 --- a/client/keys/show_test.go +++ b/client/keys/show_test.go @@ -25,7 +25,7 @@ func Test_multiSigKey_Properties(t *testing.T) { 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", tmp.GetAddress().String()) + require.Equal(t, "cosmos16wfryel63g7axeamw68630wglalcnk3l0zuadc", sdk.MustBech32ifyAddressBytes("cosmos", tmp.GetAddress())) } func Test_showKeysCmd(t *testing.T) { diff --git a/crypto/armor_test.go b/crypto/armor_test.go index 621a8bf38eb..515cbd1e552 100644 --- a/crypto/armor_test.go +++ b/crypto/armor_test.go @@ -17,6 +17,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto" "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/types" ) func TestArmorUnarmorPrivKey(t *testing.T) { @@ -70,7 +71,7 @@ func TestArmorUnarmorPubKey(t *testing.T) { cstore := keyring.NewInMemory() // Add keys and see they return in alphabetical order - info, _, err := cstore.NewMnemonic("Bob", keyring.English, keyring.AltSecp256k1) + info, _, err := cstore.NewMnemonic("Bob", keyring.English, types.FullFundraiserPath, keyring.AltSecp256k1) require.NoError(t, err) armored := crypto.ArmorPubKeyBytes(info.GetPubKey().Bytes(), "") pubBytes, algo, err := crypto.UnarmorPubKeyBytes(armored) diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 25e0d68c943..6987a25eabc 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -43,9 +43,6 @@ const ( var ( _ Keyring = &keystore{} maxPassphraseEntryAttempts = 3 - - // TODO: remove and add to methods parameters - config = sdk.GetConfig() ) // Keyring exposes operations over a backend supported by github.com/99designs/keyring. @@ -65,13 +62,13 @@ type Keyring interface { // key from that, and persists it to the storage. Returns the generated mnemonic and the key // Info. It returns an error if it fails to generate a key for the given algo type, or if // another key is already stored under the same name. - NewMnemonic(uid string, language Language, algo SignatureAlgo) (Info, string, error) + NewMnemonic(uid string, language Language, hdPath string, algo SignatureAlgo) (Info, string, error) // NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it. NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SignatureAlgo) (Info, error) // SaveLedgerKey retrieves a public key reference from a Ledger device and persists it. - SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, account, coinType, index uint32) (Info, error) + SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, coinType, account, index uint32) (Info, error) // SavePubKey stores a public key and returns the persisted Info structure. SavePubKey(uid string, pubkey tmcrypto.PubKey, algo pubKeyType) (Info, error) @@ -328,7 +325,7 @@ func (ks keystore) SignByAddress(address sdk.Address, msg []byte) ([]byte, tmcry return ks.Sign(key.GetName(), msg) } -func (ks keystore) SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, account, coinType, index uint32) (Info, error) { +func (ks keystore) SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, coinType, account, index uint32) (Info, error) { if !ks.options.supportedAlgosLedger.Contains(algo) { return nil, ErrUnsupportedSigningAlgo } @@ -444,7 +441,7 @@ func (ks keystore) List() ([]Info, error) { return res, nil } -func (ks keystore) NewMnemonic(uid string, language Language, algo SignatureAlgo) (Info, string, error) { +func (ks keystore) NewMnemonic(uid string, language Language, hdPath string, algo SignatureAlgo) (Info, string, error) { if language != English { return nil, "", ErrUnsupportedLanguage } @@ -465,7 +462,7 @@ func (ks keystore) NewMnemonic(uid string, language Language, algo SignatureAlgo return nil, "", err } - info, err := ks.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, config.GetFullFundraiserPath(), algo) + info, err := ks.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, hdPath, algo) if err != nil { return nil, "", err } diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 0583bcd14ae..6705f888df1 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -16,6 +16,7 @@ import ( "github.com/cosmos/cosmos-sdk/crypto" "github.com/cosmos/cosmos-sdk/crypto/keys/hd" "github.com/cosmos/cosmos-sdk/tests" + "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -42,7 +43,7 @@ func TestNewKeyring(t *testing.T) { require.Equal(t, "unknown keyring backend fuzzy", err.Error()) mockIn.Reset("password\npassword\n") - info, _, err := kr.NewMnemonic("foo", English, AltSecp256k1) + info, _, err := kr.NewMnemonic("foo", English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) require.Equal(t, "foo", info.GetName()) } @@ -61,17 +62,17 @@ func TestKeyManagementKeyRing(t *testing.T) { require.Nil(t, err) require.Empty(t, l) - _, _, err = kb.NewMnemonic(n1, English, notSupportedAlgo{}) + _, _, err = kb.NewMnemonic(n1, English, types.FullFundraiserPath, notSupportedAlgo{}) require.Error(t, err, "ed25519 keys are currently not supported by keybase") // create some keys _, err = kb.Key(n1) require.Error(t, err) - i, _, err := kb.NewMnemonic(n1, English, algo) + i, _, err := kb.NewMnemonic(n1, English, types.FullFundraiserPath, algo) require.NoError(t, err) require.Equal(t, n1, i.GetName()) - _, _, err = kb.NewMnemonic(n2, English, algo) + _, _, err = kb.NewMnemonic(n2, English, types.FullFundraiserPath, algo) require.NoError(t, err) // we can get these keys @@ -137,7 +138,7 @@ func TestSignVerifyKeyRingWithLedger(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - i1, err := kb.SaveLedgerKey("key", AltSecp256k1, "cosmos", 0, 118, 0) + i1, err := kb.SaveLedgerKey("key", AltSecp256k1, "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") @@ -158,7 +159,7 @@ func TestSignVerifyKeyRingWithLedger(t *testing.T) { require.True(t, i1.GetPubKey().VerifyBytes(d1, s1)) require.True(t, bytes.Equal(s1, s2)) - localInfo, _, err := kb.NewMnemonic("test", English, AltSecp256k1) + localInfo, _, err := kb.NewMnemonic("test", English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) _, _, err = SignWithLedger(localInfo, d1) require.Error(t, err) @@ -176,10 +177,10 @@ func TestSignVerifyKeyRing(t *testing.T) { n1, n2, n3 := "some dude", "a dudette", "dude-ish" // create two users and get their info - i1, _, err := kb.NewMnemonic(n1, English, algo) + i1, _, err := kb.NewMnemonic(n1, English, types.FullFundraiserPath, algo) require.Nil(t, err) - i2, _, err := kb.NewMnemonic(n2, English, algo) + i2, _, err := kb.NewMnemonic(n2, English, types.FullFundraiserPath, algo) require.Nil(t, err) // Import a public key @@ -249,7 +250,7 @@ func TestExportImportKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - info, _, err := kb.NewMnemonic("john", English, AltSecp256k1) + info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) require.Equal(t, info.GetName(), "john") @@ -283,7 +284,7 @@ func TestExportImportPubKeyKeyRing(t *testing.T) { algo := AltSecp256k1 // CreateMnemonic a private-public key pair and ensure consistency - info, _, err := kb.NewMnemonic("john", English, algo) + info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, algo) require.Nil(t, err) require.NotEqual(t, info, "") require.Equal(t, info.GetName(), "john") @@ -325,7 +326,7 @@ func TestAdvancedKeyManagementKeyRing(t *testing.T) { n1, n2 := "old-name", "new name" // make sure key works with initial password - _, _, err = kb.NewMnemonic(n1, English, algo) + _, _, err = kb.NewMnemonic(n1, English, types.FullFundraiserPath, algo) require.Nil(t, err, "%+v", err) _, err = kb.ExportPubKeyArmor(n1 + ".notreal") @@ -358,7 +359,7 @@ func TestSeedPhraseKeyRing(t *testing.T) { n1, n2 := "lost-key", "found-again" // make sure key works with initial password - info, mnemonic, err := kb.NewMnemonic(n1, English, algo) + info, mnemonic, err := kb.NewMnemonic(n1, English, types.FullFundraiserPath, algo) require.Nil(t, err, "%+v", err) require.Equal(t, n1, info.GetName()) require.NotEmpty(t, mnemonic) @@ -385,7 +386,7 @@ func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - _, _, err = kb.NewMnemonic("john", English, AltSecp256k1) + _, _, err = kb.NewMnemonic("john", English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) keystr, err := kb.ExportPrivKeyArmor("john", "somepassword") @@ -410,7 +411,7 @@ func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { func TestInMemoryLanguage(t *testing.T) { kb := NewInMemory() - _, _, err := kb.NewMnemonic("something", Japanese, AltSecp256k1) + _, _, err := kb.NewMnemonic("something", Japanese, types.FullFundraiserPath, AltSecp256k1) require.Error(t, err) require.Equal(t, "unsupported language: only english is supported", err.Error()) } @@ -439,7 +440,7 @@ func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { func TestInMemoryCreateLedger(t *testing.T) { kb := NewInMemory() - ledger, err := kb.SaveLedgerKey("some_account", AltSecp256k1, "cosmos", 3, 118, 1) + ledger, err := kb.SaveLedgerKey("some_account", AltSecp256k1, "cosmos", 118, 3, 1) if err != nil { require.Error(t, err) @@ -484,17 +485,17 @@ func TestInMemoryKeyManagement(t *testing.T) { require.Nil(t, err) require.Empty(t, l) - _, _, err = cstore.NewMnemonic(n1, English, notSupportedAlgo{}) + _, _, err = cstore.NewMnemonic(n1, English, types.FullFundraiserPath, notSupportedAlgo{}) require.Error(t, err, "ed25519 keys are currently not supported by keybase") // create some keys _, err = cstore.Key(n1) require.Error(t, err) - i, _, err := cstore.NewMnemonic(n1, English, algo) + i, _, err := cstore.NewMnemonic(n1, English, types.FullFundraiserPath, algo) require.NoError(t, err) require.Equal(t, n1, i.GetName()) - _, _, err = cstore.NewMnemonic(n2, English, algo) + _, _, err = cstore.NewMnemonic(n2, English, types.FullFundraiserPath, algo) require.NoError(t, err) // we can get these keys @@ -564,10 +565,10 @@ func TestInMemorySignVerify(t *testing.T) { n1, n2, n3 := "some dude", "a dudette", "dude-ish" // create two users and get their info - i1, _, err := cstore.NewMnemonic(n1, English, algo) + i1, _, err := cstore.NewMnemonic(n1, English, types.FullFundraiserPath, algo) require.Nil(t, err) - i2, _, err := cstore.NewMnemonic(n2, English, algo) + i2, _, err := cstore.NewMnemonic(n2, English, types.FullFundraiserPath, algo) require.Nil(t, err) // Import a public key @@ -636,7 +637,7 @@ func TestInMemoryExportImport(t *testing.T) { // make the storage with reasonable defaults cstore := NewInMemory() - info, _, err := cstore.NewMnemonic("john", English, AltSecp256k1) + info, _, err := cstore.NewMnemonic("john", English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) require.Equal(t, info.GetName(), "john") @@ -664,7 +665,7 @@ func TestInMemoryExportImport(t *testing.T) { func TestInMemoryExportImportPrivKey(t *testing.T) { kb := NewInMemory() - info, _, err := kb.NewMnemonic("john", English, AltSecp256k1) + info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) require.Equal(t, info.GetName(), "john") priv1, err := kb.Key("john") @@ -692,7 +693,7 @@ func TestInMemoryExportImportPubKey(t *testing.T) { cstore := NewInMemory() // CreateMnemonic a private-public key pair and ensure consistency - info, _, err := cstore.NewMnemonic("john", English, AltSecp256k1) + info, _, err := cstore.NewMnemonic("john", English, types.FullFundraiserPath, AltSecp256k1) require.Nil(t, err) require.NotEqual(t, info, "") require.Equal(t, info.GetName(), "john") @@ -733,7 +734,7 @@ func TestInMemoryAdvancedKeyManagement(t *testing.T) { n1, n2 := "old-name", "new name" // make sure key works with initial password - _, _, err := cstore.NewMnemonic(n1, English, algo) + _, _, err := cstore.NewMnemonic(n1, English, types.FullFundraiserPath, algo) require.Nil(t, err, "%+v", err) // exporting requires the proper name and passphrase @@ -767,7 +768,7 @@ func TestInMemorySeedPhrase(t *testing.T) { n1, n2 := "lost-key", "found-again" // make sure key works with initial password - info, mnemonic, err := cstore.NewMnemonic(n1, English, algo) + info, mnemonic, err := cstore.NewMnemonic(n1, English, types.FullFundraiserPath, algo) require.Nil(t, err, "%+v", err) require.Equal(t, n1, info.GetName()) require.NotEmpty(t, mnemonic) @@ -795,7 +796,7 @@ func ExampleNew() { sec := AltSecp256k1 // Add keys and see they return in alphabetical order - bob, _, err := cstore.NewMnemonic("Bob", English, sec) + bob, _, err := cstore.NewMnemonic("Bob", English, types.FullFundraiserPath, sec) if err != nil { // this should never happen fmt.Println(err) @@ -803,8 +804,8 @@ func ExampleNew() { // return info here just like in List fmt.Println(bob.GetName()) } - _, _, _ = cstore.NewMnemonic("Alice", English, sec) - _, _, _ = cstore.NewMnemonic("Carl", English, sec) + _, _, _ = cstore.NewMnemonic("Alice", English, types.FullFundraiserPath, sec) + _, _, _ = cstore.NewMnemonic("Carl", English, types.FullFundraiserPath, sec) info, _ := cstore.List() for _, i := range info { fmt.Println(i.GetName()) @@ -850,16 +851,16 @@ func TestAltKeyring_List(t *testing.T) { require.Empty(t, list) // Fails on creating unsupported pubKeyType - _, _, err = keyring.NewMnemonic("failing", English, notSupportedAlgo{}) + _, _, err = keyring.NewMnemonic("failing", English, types.FullFundraiserPath, notSupportedAlgo{}) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) // Create 3 keys uid1, uid2, uid3 := "Zkey", "Bkey", "Rkey" - _, _, err = keyring.NewMnemonic(uid1, English, AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid1, English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) - _, _, err = keyring.NewMnemonic(uid2, English, AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid2, English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) - _, _, err = keyring.NewMnemonic(uid3, English, AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid3, English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) list, err = keyring.List() @@ -888,10 +889,10 @@ func TestAltKeyring_NewAccount(t *testing.T) { uid := "newUid" // Fails on creating unsupported pubKeyType - _, err = keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, config.GetFullFundraiserPath(), notSupportedAlgo{}) + _, err = keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.FullFundraiserPath, notSupportedAlgo{}) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) - info, err := keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, config.GetFullFundraiserPath(), AltSecp256k1) + info, err := keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) require.Equal(t, uid, info.GetName()) @@ -909,10 +910,10 @@ func TestAltKeyring_SaveLedgerKey(t *testing.T) { require.NoError(t, err) // Test unsupported Algo - _, err = keyring.SaveLedgerKey("key", notSupportedAlgo{}, "cosmos", 0, 118, 0) + _, err = keyring.SaveLedgerKey("key", notSupportedAlgo{}, "cosmos", 118, 0, 0) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) - ledger, err := keyring.SaveLedgerKey("some_account", AltSecp256k1, "cosmos", 3, 118, 1) + ledger, err := keyring.SaveLedgerKey("some_account", AltSecp256k1, "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") @@ -949,7 +950,7 @@ func TestAltKeyring_Get(t *testing.T) { require.NoError(t, err) uid := someKey - mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) key, err := keyring.Key(uid) @@ -965,7 +966,7 @@ func TestAltKeyring_KeyByAddress(t *testing.T) { require.NoError(t, err) uid := someKey - mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) key, err := keyring.KeyByAddress(mnemonic.GetAddress()) @@ -981,7 +982,7 @@ func TestAltKeyring_Delete(t *testing.T) { require.NoError(t, err) uid := someKey - _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) list, err := keyring.List() @@ -1004,7 +1005,7 @@ func TestAltKeyring_DeleteByAddress(t *testing.T) { require.NoError(t, err) uid := someKey - mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) list, err := keyring.List() @@ -1052,9 +1053,9 @@ func TestAltKeyring_SaveMultisig(t *testing.T) { keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - mnemonic1, _, err := keyring.NewMnemonic("key1", English, AltSecp256k1) + mnemonic1, _, err := keyring.NewMnemonic("key1", English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) - mnemonic2, _, err := keyring.NewMnemonic("key2", English, AltSecp256k1) + mnemonic2, _, err := keyring.NewMnemonic("key2", English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) key := "multi" @@ -1078,7 +1079,7 @@ func TestAltKeyring_Sign(t *testing.T) { require.NoError(t, err) uid := "jack" - _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) msg := []byte("some message") @@ -1097,7 +1098,7 @@ func TestAltKeyring_SignByAddress(t *testing.T) { require.NoError(t, err) uid := "jack" - mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) msg := []byte("some message") @@ -1116,7 +1117,7 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { require.NoError(t, err) uid := theID - _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) passphrase := "somePass" @@ -1144,7 +1145,7 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { require.NoError(t, err) uid := theID - mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) passphrase := "somePass" @@ -1172,7 +1173,7 @@ func TestAltKeyring_ImportExportPubKey(t *testing.T) { require.NoError(t, err) uid := theID - _, _, err = keyring.NewMnemonic(uid, English, AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) armor, err := keyring.ExportPubKeyArmor(uid) @@ -1195,7 +1196,7 @@ func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { require.NoError(t, err) uid := theID - mnemonic, _, err := keyring.NewMnemonic(uid, English, AltSecp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) armor, err := keyring.ExportPubKeyArmorByAddress(mnemonic.GetAddress()) @@ -1218,11 +1219,11 @@ func TestAltKeyring_ConstructorSupportedAlgos(t *testing.T) { require.NoError(t, err) // should fail when using unsupported signing algorythm. - _, _, err = keyring.NewMnemonic("test", English, notSupportedAlgo{}) + _, _, err = keyring.NewMnemonic("test", English, types.FullFundraiserPath, notSupportedAlgo{}) require.EqualError(t, err, "unsupported signing algo") // but works with default signing algo. - _, _, err = keyring.NewMnemonic("test", English, AltSecp256k1) + _, _, err = keyring.NewMnemonic("test", English, types.FullFundraiserPath, AltSecp256k1) require.NoError(t, err) // but we can create a new keybase with our provided algos. @@ -1237,7 +1238,7 @@ func TestAltKeyring_ConstructorSupportedAlgos(t *testing.T) { require.NoError(t, err) // now this new keyring does not fail when signing with provided algo - _, _, err = keyring2.NewMnemonic("test", English, notSupportedAlgo{}) + _, _, err = keyring2.NewMnemonic("test", English, types.FullFundraiserPath, notSupportedAlgo{}) require.NoError(t, err) } diff --git a/server/init.go b/server/init.go index cad2ed13088..a55b8acd366 100644 --- a/server/init.go +++ b/server/init.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -12,7 +13,7 @@ import ( // phrase to recover the private key. func GenerateCoinKey() (sdk.AccAddress, string, error) { // generate a private key, with recovery phrase - info, secret, err := keyring.NewInMemory().NewMnemonic("name", keyring.English, keyring.AltSecp256k1) + info, secret, err := keyring.NewInMemory().NewMnemonic("name", keyring.English, types.FullFundraiserPath, keyring.AltSecp256k1) if err != nil { return sdk.AccAddress([]byte{}), "", err } @@ -32,7 +33,7 @@ func GenerateSaveCoinKey(keybase keyring.Keyring, keyName, keyPass string, overw } // generate a private key, with recovery phrase - info, secret, err := keybase.NewMnemonic(keyName, keyring.English, keyring.AltSecp256k1) + info, secret, err := keybase.NewMnemonic(keyName, keyring.English, types.FullFundraiserPath, keyring.AltSecp256k1) if err != nil { return sdk.AccAddress([]byte{}), "", err } From 7ef86c8ea7f80fed5ff4d1fd6cb210104f55d873 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 3 Apr 2020 19:02:56 +0200 Subject: [PATCH 116/148] fix bug when importing from same seed but different keys made that key1 lose its info --- crypto/keyring/keyring.go | 7 +- crypto/keyring/keyring_test.go | 134 ++++++++++++++++++++++----------- 2 files changed, 94 insertions(+), 47 deletions(-) diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 6987a25eabc..fd457b4aecf 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -678,7 +678,12 @@ func (ks keystore) writeInfo(name string, info Info) error { key := infoKey(name) serializedInfo := marshalInfo(info) - err := ks.db.Set(keyring.Item{ + _, err := ks.db.Get(addrHexKeyAsString(info.GetAddress())) + if err != keyring.ErrKeyNotFound { + return fmt.Errorf("public key already exist in keybase") + } + + err = ks.db.Set(keyring.Item{ Key: string(key), Data: serializedInfo, }) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 6705f888df1..2f469fb6b7d 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -183,15 +183,6 @@ func TestSignVerifyKeyRing(t *testing.T) { i2, _, err := kb.NewMnemonic(n2, English, types.FullFundraiserPath, algo) require.Nil(t, err) - // Import a public key - armor, err := kb.ExportPubKeyArmor(n2) - require.Nil(t, err) - err = kb.ImportPubKey(n3, armor) - require.NoError(t, err) - i3, err := kb.Key(n3) - require.NoError(t, err) - require.Equal(t, i3.GetName(), n3) - // let's try to sign some messages d1 := []byte("my first message") d2 := []byte("some other important info!") @@ -239,6 +230,17 @@ func TestSignVerifyKeyRing(t *testing.T) { } // Now try to sign data with a secret-less key + // Import a public key + armor, err := kb.ExportPubKeyArmor(n2) + require.Nil(t, err) + err = kb.Delete(n2) + + err = kb.ImportPubKey(n3, armor) + require.NoError(t, err) + i3, err := kb.Key(n3) + require.NoError(t, err) + require.Equal(t, i3.GetName(), n3) + _, _, err = kb.Sign(n3, d3) require.Error(t, err) require.Equal(t, "cannot sign with offline keys", err.Error()) @@ -261,6 +263,8 @@ func TestExportImportKeyRing(t *testing.T) { armor, err := kb.ExportPrivKeyArmor("john", "apassphrase") require.NoError(t, err) + err = kb.Delete("john") + require.NoError(t, err) err = kb.ImportPrivKey("john2", armor, "apassphrase") require.NoError(t, err) @@ -297,19 +301,19 @@ func TestExportImportPubKeyKeyRing(t *testing.T) { // Export the public key only armor, err := kb.ExportPubKeyArmor("john") require.NoError(t, err) + err = kb.Delete("john") + require.NoError(t, err) + // Import it under a different name err = kb.ImportPubKey("john-pubkey-only", armor) require.NoError(t, err) + // Ensure consistency john2, err := kb.Key("john-pubkey-only") require.NoError(t, err) + // Compare the public keys require.True(t, john.GetPubKey().Equals(john2.GetPubKey())) - // Ensure the original key hasn't changed - john, err = kb.Key("john") - require.NoError(t, err) - require.Equal(t, john.GetPubKey().Address(), addr) - require.Equal(t, john.GetName(), "john") // Ensure keys cannot be overwritten err = kb.ImportPubKey("john-pubkey-only", armor) @@ -319,6 +323,7 @@ func TestExportImportPubKeyKeyRing(t *testing.T) { func TestAdvancedKeyManagementKeyRing(t *testing.T) { dir, cleanup := tests.NewTestCaseDir(t) t.Cleanup(cleanup) + kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) @@ -339,6 +344,8 @@ func TestAdvancedKeyManagementKeyRing(t *testing.T) { require.NotNil(t, err) exported, err := kb.ExportPubKeyArmor(n1) require.Nil(t, err, "%+v", err) + err = kb.Delete(n1) + require.NoError(t, err) // import succeeds err = kb.ImportPubKey(n2, exported) @@ -392,6 +399,8 @@ func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { keystr, err := kb.ExportPrivKeyArmor("john", "somepassword") require.NoError(t, err) require.NotEmpty(t, keystr) + err = kb.Delete("john") + require.NoError(t, err) // try import the key - wrong password err = kb.ImportPrivKey("john2", keystr, "bad pass") @@ -571,15 +580,6 @@ func TestInMemorySignVerify(t *testing.T) { i2, _, err := cstore.NewMnemonic(n2, English, types.FullFundraiserPath, algo) require.Nil(t, err) - // Import a public key - armor, err := cstore.ExportPubKeyArmor(n2) - require.Nil(t, err) - err = cstore.ImportPubKey(n3, armor) - require.NoError(t, err) - i3, err := cstore.Key(n3) - require.NoError(t, err) - require.Equal(t, i3.GetName(), n3) - // let's try to sign some messages d1 := []byte("my first message") d2 := []byte("some other important info!") @@ -626,6 +626,17 @@ func TestInMemorySignVerify(t *testing.T) { require.Equal(t, tc.valid, valid, "%d", i) } + // Import a public key + armor, err := cstore.ExportPubKeyArmor(n2) + require.Nil(t, err) + err = cstore.Delete(n2) + require.NoError(t, err) + err = cstore.ImportPubKey(n3, armor) + require.NoError(t, err) + i3, err := cstore.Key(n3) + require.NoError(t, err) + require.Equal(t, i3.GetName(), n3) + // Now try to sign data with a secret-less key _, _, err = cstore.Sign(n3, d3) require.Error(t, err) @@ -648,6 +659,8 @@ func TestInMemoryExportImport(t *testing.T) { armor, err := cstore.ExportPubKeyArmor("john") require.NoError(t, err) + err = cstore.Delete("john") + require.NoError(t, err) err = cstore.ImportPubKey("john2", armor) require.NoError(t, err) @@ -706,6 +719,9 @@ func TestInMemoryExportImportPubKey(t *testing.T) { // Export the public key only armor, err := cstore.ExportPubKeyArmor("john") require.NoError(t, err) + err = cstore.Delete("john") + require.NoError(t, err) + // Import it under a different name err = cstore.ImportPubKey("john-pubkey-only", armor) require.NoError(t, err) @@ -714,11 +730,6 @@ func TestInMemoryExportImportPubKey(t *testing.T) { require.NoError(t, err) // Compare the public keys require.True(t, john.GetPubKey().Equals(john2.GetPubKey())) - // Ensure the original key hasn't changed - john, err = cstore.Key("john") - require.NoError(t, err) - require.Equal(t, john.GetPubKey().Address(), addr) - require.Equal(t, john.GetName(), "john") // Ensure keys cannot be overwritten err = cstore.ImportPubKey("john-pubkey-only", armor) @@ -748,6 +759,8 @@ func TestInMemoryAdvancedKeyManagement(t *testing.T) { require.NotNil(t, err) exported, err := cstore.ExportPubKeyArmor(n1) require.Nil(t, err, "%+v", err) + err = cstore.Delete(n1) + require.NoError(t, err) // import succeeds err = cstore.ImportPubKey(n2, exported) @@ -760,7 +773,6 @@ func TestInMemoryAdvancedKeyManagement(t *testing.T) { // TestInMemorySeedPhrase verifies restoring from a seed phrase func TestInMemorySeedPhrase(t *testing.T) { - // make the storage with reasonable defaults cstore := NewInMemory() @@ -789,6 +801,28 @@ func TestInMemorySeedPhrase(t *testing.T) { require.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) } +func TestKeyChain_ShouldFailWhenAddingSameGeneratedAccount(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + kr, err := New(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + // Given we create a mnemonic + _, seed, err := kr.NewMnemonic("test", English, "", AltSecp256k1) + require.NoError(t, err) + + err = kr.Delete("test") + require.NoError(t, err) + + _, err = kr.NewAccount("test1", seed, "", "", AltSecp256k1) + require.NoError(t, err) + + // Creating another account with different uid but same seed should fail due to have same pub address + _, err = kr.NewAccount("test2", seed, "", "", AltSecp256k1) + require.Error(t, err) +} + func ExampleNew() { // Select the encryption and storage for your cryptostore cstore := NewInMemory() @@ -1123,11 +1157,8 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { passphrase := "somePass" armor, err := keyring.ExportPrivKeyArmor(uid, passphrase) require.NoError(t, err) - - // Should fail importing private key on existing key. - err = keyring.ImportPrivKey(uid, armor, passphrase) - require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", uid)) - + err = keyring.Delete(uid) + require.NoError(t, err) newUID := otherID // Should fail importing with wrong password err = keyring.ImportPrivKey(newUID, armor, "wrongPass") @@ -1135,6 +1166,10 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { err = keyring.ImportPrivKey(newUID, armor, passphrase) require.NoError(t, err) + + // Should fail importing private key on existing key. + err = keyring.ImportPrivKey(newUID, armor, passphrase) + require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", newUID)) } func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { @@ -1151,10 +1186,8 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { passphrase := "somePass" armor, err := keyring.ExportPrivKeyArmorByAddress(mnemonic.GetAddress(), passphrase) require.NoError(t, err) - - // Should fail importing private key on existing key. - err = keyring.ImportPrivKey(uid, armor, passphrase) - require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", uid)) + err = keyring.Delete(uid) + require.NoError(t, err) newUID := otherID // Should fail importing with wrong password @@ -1163,6 +1196,11 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { err = keyring.ImportPrivKey(newUID, armor, passphrase) require.NoError(t, err) + + // Should fail importing private key on existing key. + err = keyring.ImportPrivKey(newUID, armor, passphrase) + require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", newUID)) + } func TestAltKeyring_ImportExportPubKey(t *testing.T) { @@ -1178,14 +1216,16 @@ func TestAltKeyring_ImportExportPubKey(t *testing.T) { armor, err := keyring.ExportPubKeyArmor(uid) require.NoError(t, err) - - // Should fail importing private key on existing key. - err = keyring.ImportPubKey(uid, armor) - require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", uid)) + err = keyring.Delete(uid) + require.NoError(t, err) newUID := otherID err = keyring.ImportPubKey(newUID, armor) require.NoError(t, err) + + // Should fail importing private key on existing key. + err = keyring.ImportPubKey(newUID, armor) + require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", newUID)) } func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { @@ -1201,14 +1241,16 @@ func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { armor, err := keyring.ExportPubKeyArmorByAddress(mnemonic.GetAddress()) require.NoError(t, err) - - // Should fail importing private key on existing key. - err = keyring.ImportPubKey(uid, armor) - require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", uid)) + err = keyring.Delete(uid) + require.NoError(t, err) newUID := otherID err = keyring.ImportPubKey(newUID, armor) require.NoError(t, err) + + // Should fail importing private key on existing key. + err = keyring.ImportPubKey(newUID, armor) + require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", newUID)) } func TestAltKeyring_ConstructorSupportedAlgos(t *testing.T) { From 321a57438b1eefdfdd1f0cee6fe6aff3b68180d8 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Fri, 3 Apr 2020 19:51:41 +0200 Subject: [PATCH 117/148] improve tests --- crypto/keyring/keyring_test.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 2f469fb6b7d..49d770493f0 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -232,11 +232,10 @@ func TestSignVerifyKeyRing(t *testing.T) { // Now try to sign data with a secret-less key // Import a public key armor, err := kb.ExportPubKeyArmor(n2) - require.Nil(t, err) - err = kb.Delete(n2) - - err = kb.ImportPubKey(n3, armor) require.NoError(t, err) + require.NoError(t, kb.Delete(n2)) + + require.NoError(t, kb.ImportPubKey(n3, armor)) i3, err := kb.Key(n3) require.NoError(t, err) require.Equal(t, i3.GetName(), n3) @@ -812,14 +811,14 @@ func TestKeyChain_ShouldFailWhenAddingSameGeneratedAccount(t *testing.T) { _, seed, err := kr.NewMnemonic("test", English, "", AltSecp256k1) require.NoError(t, err) - err = kr.Delete("test") - require.NoError(t, err) + require.NoError(t, kr.Delete("test")) - _, err = kr.NewAccount("test1", seed, "", "", AltSecp256k1) + path := hd.CreateHDPath(118, 0, 0).String() + _, err = kr.NewAccount("test1", seed, "", path, AltSecp256k1) require.NoError(t, err) // Creating another account with different uid but same seed should fail due to have same pub address - _, err = kr.NewAccount("test2", seed, "", "", AltSecp256k1) + _, err = kr.NewAccount("test2", seed, "", path, AltSecp256k1) require.Error(t, err) } From abf382c137cbe5d95b70b0975b006de8077c1dae Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 3 Apr 2020 22:33:18 +0200 Subject: [PATCH 118/148] change options struct to make it public --- crypto/keyring/keyring.go | 21 +++++++++++---------- crypto/keyring/keyring_test.go | 4 ++-- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index fd457b4aecf..35d9280a965 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -151,14 +151,14 @@ func New( type keystore struct { db keyring.Keyring - options keyringOptions + options Options } func newKeystore(kr keyring.Keyring, opts ...Option) keystore { // Default options for keybase - options := keyringOptions{ - supportedAlgos: SigningAlgoList{AltSecp256k1}, - supportedAlgosLedger: SigningAlgoList{AltSecp256k1}, + options := Options{ + SupportedAlgos: SigningAlgoList{AltSecp256k1}, + SupportedAlgosLedger: SigningAlgoList{AltSecp256k1}, } for _, optionFn := range opts { @@ -326,7 +326,7 @@ func (ks keystore) SignByAddress(address sdk.Address, msg []byte) ([]byte, tmcry } func (ks keystore) SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, coinType, account, index uint32) (Info, error) { - if !ks.options.supportedAlgosLedger.Contains(algo) { + if !ks.options.SupportedAlgosLedger.Contains(algo) { return nil, ErrUnsupportedSigningAlgo } @@ -487,7 +487,7 @@ func (ks keystore) NewAccount(uid string, mnemonic string, bip39Passphrase strin } func (ks keystore) isSupportedSigningAlgo(algo SignatureAlgo) bool { - return ks.options.supportedAlgos.Contains(algo) + return ks.options.SupportedAlgos.Contains(algo) } func (ks keystore) Key(uid string) (Info, error) { @@ -506,11 +506,12 @@ func (ks keystore) Key(uid string) (Info, error) { } // Option overrides keyring configuration options. -type Option func(options *keyringOptions) +type Option func(options *Options) -type keyringOptions struct { - supportedAlgos SigningAlgoList - supportedAlgosLedger SigningAlgoList +//Options define the options of the Keyring +type Options struct { + SupportedAlgos SigningAlgoList + SupportedAlgosLedger SigningAlgoList } // SignWithLedger signs a binary message with the ledger device referenced by an Info object diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 49d770493f0..256dc3db968 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -1271,8 +1271,8 @@ func TestAltKeyring_ConstructorSupportedAlgos(t *testing.T) { dir2, clean2 := tests.NewTestCaseDir(t) t.Cleanup(clean2) - keyring2, err := New(t.Name(), BackendTest, dir2, nil, func(options *keyringOptions) { - options.supportedAlgos = SigningAlgoList{ + keyring2, err := New(t.Name(), BackendTest, dir2, nil, func(options *Options) { + options.SupportedAlgos = SigningAlgoList{ notSupportedAlgo{}, } }) From 78508f13900c651cf91af3786d2cb55f33777ebe Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 3 Apr 2020 23:31:33 +0200 Subject: [PATCH 119/148] move algo --- client/keys/add.go | 7 +- client/keys/delete_test.go | 5 +- client/keys/export_test.go | 3 +- client/keys/list_test.go | 3 +- client/keys/show_test.go | 5 +- crypto/algo/algo.go | 69 ++++++++++++++++ crypto/armor_test.go | 7 +- crypto/keyring/info.go | 42 +++++----- crypto/keyring/keyring.go | 19 ++--- crypto/keyring/keyring_test.go | 98 ++++++++++++----------- crypto/keyring/signing_algorithms.go | 77 ++---------------- crypto/keyring/signing_algorithms_test.go | 30 +++---- crypto/keyring/types.go | 9 ++- crypto/keyring/types_test.go | 3 +- server/init.go | 5 +- server/init_test.go | 5 +- 16 files changed, 205 insertions(+), 182 deletions(-) create mode 100644 crypto/algo/algo.go diff --git a/client/keys/add.go b/client/keys/add.go index afbcc030092..3c2bc02fdda 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -5,6 +5,7 @@ import ( "bytes" "errors" "fmt" + algo2 "github.com/cosmos/cosmos-sdk/crypto/algo" "io" "sort" @@ -79,7 +80,7 @@ the flag --nosort is set. cmd.Flags().Uint32(flagAccount, 0, "Account number for HD derivation") cmd.Flags().Uint32(flagIndex, 0, "Address index number for HD derivation") cmd.Flags().Bool(flags.FlagIndentResponse, false, "Add indent to JSON response") - cmd.Flags().String(flagKeyAlgo, string(keyring.Secp256k1), "Key signing algorithm to generate keys for") + cmd.Flags().String(flagKeyAlgo, string(algo2.Secp256k1), "Key signing algorithm to generate keys for") return cmd } @@ -120,7 +121,7 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *buf algo, err := keyring.NewSigningAlgoFromString(viper.GetString(flagKeyAlgo)) if err != nil { - algo = keyring.AltSecp256k1 + algo = algo2.AltSecp256k1 } if !viper.GetBool(flags.FlagDryRun) { @@ -203,7 +204,7 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *buf } bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix() - info, err := kb.SaveLedgerKey(name, keyring.AltSecp256k1, bech32PrefixAccAddr, coinType, account, index) + info, err := kb.SaveLedgerKey(name, algo2.AltSecp256k1, bech32PrefixAccAddr, coinType, account, index) if err != nil { return err } diff --git a/client/keys/delete_test.go b/client/keys/delete_test.go index 4f741c8853d..71d2e4bb18c 100644 --- a/client/keys/delete_test.go +++ b/client/keys/delete_test.go @@ -1,6 +1,7 @@ package keys import ( + "github.com/cosmos/cosmos-sdk/crypto/algo" "testing" "github.com/spf13/viper" @@ -34,9 +35,9 @@ func Test_runDeleteCmd(t *testing.T) { backend := viper.GetString(flags.FlagKeyringBackend) kb, err := keyring.New(sdk.KeyringServiceName(), backend, kbHome, mockIn) require.NoError(t, err) - _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, keyring.AltSecp256k1) + _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, algo.AltSecp256k1) require.NoError(t, err) - _, _, err = kb.NewMnemonic(fakeKeyName2, keyring.English, sdk.FullFundraiserPath, keyring.AltSecp256k1) + _, _, err = kb.NewMnemonic(fakeKeyName2, keyring.English, sdk.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) err = runDeleteCmd(deleteKeyCommand, []string{"blah"}) diff --git a/client/keys/export_test.go b/client/keys/export_test.go index 2b83ecd822a..9ffa6615efc 100644 --- a/client/keys/export_test.go +++ b/client/keys/export_test.go @@ -1,6 +1,7 @@ package keys import ( + "github.com/cosmos/cosmos-sdk/crypto/algo" "testing" "github.com/spf13/viper" @@ -29,7 +30,7 @@ func Test_runExportCmd(t *testing.T) { }) path := sdk.GetConfig().GetFullFundraiserPath() - _, err = kb.NewAccount("keyname1", tests.TestMnemonic, "", path, keyring.AltSecp256k1) + _, err = kb.NewAccount("keyname1", tests.TestMnemonic, "", path, algo.AltSecp256k1) require.NoError(t, err) // Now enter password diff --git a/client/keys/list_test.go b/client/keys/list_test.go index 49ecdf5c940..bd01bcc57e4 100644 --- a/client/keys/list_test.go +++ b/client/keys/list_test.go @@ -1,6 +1,7 @@ package keys import ( + "github.com/cosmos/cosmos-sdk/crypto/algo" "testing" "github.com/spf13/cobra" @@ -35,7 +36,7 @@ func Test_runListCmd(t *testing.T) { require.NoError(t, err) path := "" //sdk.GetConfig().GetFullFundraiserPath() - _, err = kb.NewAccount("something", tests.TestMnemonic, "", path, keyring.AltSecp256k1) + _, err = kb.NewAccount("something", tests.TestMnemonic, "", path, algo.AltSecp256k1) require.NoError(t, err) t.Cleanup(func() { diff --git a/client/keys/show_test.go b/client/keys/show_test.go index 210c7590531..00ba7c03aec 100644 --- a/client/keys/show_test.go +++ b/client/keys/show_test.go @@ -1,6 +1,7 @@ package keys import ( + "github.com/cosmos/cosmos-sdk/crypto/algo" "testing" "github.com/spf13/viper" @@ -57,10 +58,10 @@ func Test_runShowCmd(t *testing.T) { }) path := hd.NewFundraiserParams(1, sdk.CoinType, 0).String() - _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, keyring.AltSecp256k1) + _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, algo.AltSecp256k1) require.NoError(t, err) - _, err = kb.NewAccount(fakeKeyName2, tests.TestMnemonic, "", path, keyring.AltSecp256k1) + _, err = kb.NewAccount(fakeKeyName2, tests.TestMnemonic, "", path, algo.AltSecp256k1) require.NoError(t, err) // Now try single key diff --git a/crypto/algo/algo.go b/crypto/algo/algo.go new file mode 100644 index 00000000000..beb7fd61c20 --- /dev/null +++ b/crypto/algo/algo.go @@ -0,0 +1,69 @@ +package algo + +import ( + "github.com/cosmos/go-bip39" + "github.com/tendermint/tendermint/crypto" + "github.com/tendermint/tendermint/crypto/secp256k1" + + "github.com/cosmos/cosmos-sdk/crypto/keys/hd" +) + +// PubKeyType defines an algorithm to derive key-pairs which can be used for cryptographic signing. +type PubKeyType string + +const ( + // MultiAlgo implies that a pubkey is a multisignature + MultiAlgo = PubKeyType("multi") + // Secp256k1 uses the Bitcoin secp256k1 ECDSA parameters. + Secp256k1 = PubKeyType("secp256k1") + // Ed25519 represents the Ed25519 signature system. + // It is currently not supported for end-user keys (wallets/ledgers). + Ed25519 = PubKeyType("ed25519") + // Sr25519 represents the Sr25519 signature system. + Sr25519 = PubKeyType("sr25519") +) + +type DeriveKeyFn func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) +type PrivKeyGenFn func(bz []byte) crypto.PrivKey + +type secp256k1Algo struct { +} + +func (s secp256k1Algo) Name() PubKeyType { + return Secp256k1 +} + +func (s secp256k1Algo) DeriveKey() DeriveKeyFn { + return Secp256k1DeriveKey +} + +func (s secp256k1Algo) PrivKeyGen() PrivKeyGenFn { + return Secp256k1PrivKeyGen +} + +var ( + // Secp256k1 uses the Bitcoin secp256k1 ECDSA parameters. + AltSecp256k1 = secp256k1Algo{} +) + +// Secp256k1PrivKeyGen generates a secp256k1 private key from the given bytes +func Secp256k1PrivKeyGen(bz []byte) crypto.PrivKey { + var bzArr [32]byte + copy(bzArr[:], bz) + return secp256k1.PrivKeySecp256k1(bzArr) +} + +// Secp256k1DeriveKey derives and returns the secp256k1 private key for the given seed and HD path. +func Secp256k1DeriveKey(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) { + seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase) + if err != nil { + return nil, err + } + + masterPriv, ch := hd.ComputeMastersFromSeed(seed) + if len(hdPath) == 0 { + return masterPriv[:], nil + } + derivedKey, err := hd.DerivePrivateKeyForPath(masterPriv, ch, hdPath) + return derivedKey[:], err +} diff --git a/crypto/armor_test.go b/crypto/armor_test.go index 515cbd1e552..ebcc657231f 100644 --- a/crypto/armor_test.go +++ b/crypto/armor_test.go @@ -4,6 +4,7 @@ import ( "bytes" "errors" "fmt" + algo2 "github.com/cosmos/cosmos-sdk/crypto/algo" "io" "testing" @@ -27,7 +28,7 @@ func TestArmorUnarmorPrivKey(t *testing.T) { require.Error(t, err) decrypted, algo, err := crypto.UnarmorDecryptPrivKey(armored, "passphrase") require.NoError(t, err) - require.Equal(t, string(keyring.Secp256k1), algo) + require.Equal(t, string(algo2.Secp256k1), algo) require.True(t, priv.Equals(decrypted)) // empty string @@ -71,14 +72,14 @@ func TestArmorUnarmorPubKey(t *testing.T) { cstore := keyring.NewInMemory() // Add keys and see they return in alphabetical order - info, _, err := cstore.NewMnemonic("Bob", keyring.English, types.FullFundraiserPath, keyring.AltSecp256k1) + info, _, err := cstore.NewMnemonic("Bob", keyring.English, types.FullFundraiserPath, algo2.AltSecp256k1) require.NoError(t, err) armored := crypto.ArmorPubKeyBytes(info.GetPubKey().Bytes(), "") pubBytes, algo, err := crypto.UnarmorPubKeyBytes(armored) require.NoError(t, err) pub, err := cryptoAmino.PubKeyFromBytes(pubBytes) require.NoError(t, err) - require.Equal(t, string(keyring.Secp256k1), algo) + require.Equal(t, string(algo2.Secp256k1), algo) require.True(t, pub.Equals(info.GetPubKey())) armored = crypto.ArmorPubKeyBytes(info.GetPubKey().Bytes(), "unknown") diff --git a/crypto/keyring/info.go b/crypto/keyring/info.go index 4f41b3e1a03..db1966a9810 100644 --- a/crypto/keyring/info.go +++ b/crypto/keyring/info.go @@ -3,6 +3,8 @@ package keyring import ( "fmt" + "github.com/cosmos/cosmos-sdk/crypto/algo" + "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/multisig" @@ -23,7 +25,7 @@ type Info interface { // Bip44 Path GetPath() (*hd.BIP44Params, error) // Algo - GetAlgo() pubKeyType + GetAlgo() algo.PubKeyType } var ( @@ -36,13 +38,13 @@ var ( // localInfo is the public information about a locally stored key // Note: Algo must be last field in struct for backwards amino compatibility type localInfo struct { - Name string `json:"name"` - PubKey crypto.PubKey `json:"pubkey"` - PrivKeyArmor string `json:"privkey.armor"` - Algo pubKeyType `json:"algo"` + Name string `json:"name"` + PubKey crypto.PubKey `json:"pubkey"` + PrivKeyArmor string `json:"privkey.armor"` + Algo algo.PubKeyType `json:"algo"` } -func newLocalInfo(name string, pub crypto.PubKey, privArmor string, algo pubKeyType) Info { +func newLocalInfo(name string, pub crypto.PubKey, privArmor string, algo algo.PubKeyType) Info { return &localInfo{ Name: name, PubKey: pub, @@ -72,7 +74,7 @@ func (i localInfo) GetAddress() types.AccAddress { } // GetType implements Info interface -func (i localInfo) GetAlgo() pubKeyType { +func (i localInfo) GetAlgo() algo.PubKeyType { return i.Algo } @@ -84,13 +86,13 @@ func (i localInfo) GetPath() (*hd.BIP44Params, error) { // ledgerInfo is the public information about a Ledger key // Note: Algo must be last field in struct for backwards amino compatibility type ledgerInfo struct { - Name string `json:"name"` - PubKey crypto.PubKey `json:"pubkey"` - Path hd.BIP44Params `json:"path"` - Algo pubKeyType `json:"algo"` + Name string `json:"name"` + PubKey crypto.PubKey `json:"pubkey"` + Path hd.BIP44Params `json:"path"` + Algo algo.PubKeyType `json:"algo"` } -func newLedgerInfo(name string, pub crypto.PubKey, path hd.BIP44Params, algo pubKeyType) Info { +func newLedgerInfo(name string, pub crypto.PubKey, path hd.BIP44Params, algo algo.PubKeyType) Info { return &ledgerInfo{ Name: name, PubKey: pub, @@ -120,7 +122,7 @@ func (i ledgerInfo) GetAddress() types.AccAddress { } // GetPath implements Info interface -func (i ledgerInfo) GetAlgo() pubKeyType { +func (i ledgerInfo) GetAlgo() algo.PubKeyType { return i.Algo } @@ -133,12 +135,12 @@ func (i ledgerInfo) GetPath() (*hd.BIP44Params, error) { // offlineInfo is the public information about an offline key // Note: Algo must be last field in struct for backwards amino compatibility type offlineInfo struct { - Name string `json:"name"` - PubKey crypto.PubKey `json:"pubkey"` - Algo pubKeyType `json:"algo"` + Name string `json:"name"` + PubKey crypto.PubKey `json:"pubkey"` + Algo algo.PubKeyType `json:"algo"` } -func newOfflineInfo(name string, pub crypto.PubKey, algo pubKeyType) Info { +func newOfflineInfo(name string, pub crypto.PubKey, algo algo.PubKeyType) Info { return &offlineInfo{ Name: name, PubKey: pub, @@ -162,7 +164,7 @@ func (i offlineInfo) GetPubKey() crypto.PubKey { } // GetAlgo returns the signing algorithm for the key -func (i offlineInfo) GetAlgo() pubKeyType { +func (i offlineInfo) GetAlgo() algo.PubKeyType { return i.Algo } @@ -228,8 +230,8 @@ func (i multiInfo) GetAddress() types.AccAddress { } // GetPath implements Info interface -func (i multiInfo) GetAlgo() pubKeyType { - return MultiAlgo +func (i multiInfo) GetAlgo() algo.PubKeyType { + return algo.MultiAlgo } // GetPath implements Info interface diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 35d9280a965..a792a9cec94 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -20,6 +20,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/input" "github.com/cosmos/cosmos-sdk/crypto" + salgo "github.com/cosmos/cosmos-sdk/crypto/algo" "github.com/cosmos/cosmos-sdk/crypto/keys/hd" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" @@ -71,7 +72,7 @@ type Keyring interface { SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, coinType, account, index uint32) (Info, error) // SavePubKey stores a public key and returns the persisted Info structure. - SavePubKey(uid string, pubkey tmcrypto.PubKey, algo pubKeyType) (Info, error) + SavePubKey(uid string, pubkey tmcrypto.PubKey, algo salgo.PubKeyType) (Info, error) // SaveMultisig stores and returns a new multsig (offline) key reference. SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) @@ -157,8 +158,8 @@ type keystore struct { func newKeystore(kr keyring.Keyring, opts ...Option) keystore { // Default options for keybase options := Options{ - SupportedAlgos: SigningAlgoList{AltSecp256k1}, - SupportedAlgosLedger: SigningAlgoList{AltSecp256k1}, + SupportedAlgos: SigningAlgoList{salgo.AltSecp256k1}, + SupportedAlgosLedger: SigningAlgoList{salgo.AltSecp256k1}, } for _, optionFn := range opts { @@ -251,7 +252,7 @@ func (ks keystore) ImportPrivKey(uid, armor, passphrase string) error { return errors.Wrap(err, "failed to decrypt private key") } - _, err = ks.writeLocalKey(uid, privKey, pubKeyType(algo)) + _, err = ks.writeLocalKey(uid, privKey, salgo.PubKeyType(algo)) if err != nil { return err } @@ -274,7 +275,7 @@ func (ks keystore) ImportPubKey(uid string, armor string) error { return err } - _, err = ks.writeOfflineKey(uid, pubKey, pubKeyType(algo)) + _, err = ks.writeOfflineKey(uid, pubKey, salgo.PubKeyType(algo)) if err != nil { return err } @@ -340,7 +341,7 @@ func (ks keystore) SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, coi return ks.writeLedgerKey(uid, priv.PubKey(), *hdPath, algo.Name()) } -func (ks keystore) writeLedgerKey(name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo pubKeyType) (Info, error) { +func (ks keystore) writeLedgerKey(name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo salgo.PubKeyType) (Info, error) { info := newLedgerInfo(name, pub, path, algo) err := ks.writeInfo(name, info) if err != nil { @@ -354,7 +355,7 @@ func (ks keystore) SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error return ks.writeMultisigKey(uid, pubkey) } -func (ks keystore) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo pubKeyType) (Info, error) { +func (ks keystore) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo salgo.PubKeyType) (Info, error) { return ks.writeOfflineKey(uid, pubkey, algo) } @@ -661,7 +662,7 @@ func newRealPrompt(dir string, buf io.Reader) func(string) (string, error) { } } -func (ks keystore) writeLocalKey(name string, priv tmcrypto.PrivKey, algo pubKeyType) (Info, error) { +func (ks keystore) writeLocalKey(name string, priv tmcrypto.PrivKey, algo salgo.PubKeyType) (Info, error) { // encrypt private key using keyring pub := priv.PubKey() @@ -703,7 +704,7 @@ func (ks keystore) writeInfo(name string, info Info) error { return nil } -func (ks keystore) writeOfflineKey(name string, pub tmcrypto.PubKey, algo pubKeyType) (Info, error) { +func (ks keystore) writeOfflineKey(name string, pub tmcrypto.PubKey, algo salgo.PubKeyType) (Info, error) { info := newOfflineInfo(name, pub, algo) err := ks.writeInfo(name, info) if err != nil { diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 256dc3db968..2e6a873979b 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -14,6 +14,8 @@ import ( "github.com/tendermint/tendermint/crypto/secp256k1" "github.com/cosmos/cosmos-sdk/crypto" + "github.com/cosmos/cosmos-sdk/crypto/algo" + salgo "github.com/cosmos/cosmos-sdk/crypto/algo" "github.com/cosmos/cosmos-sdk/crypto/keys/hd" "github.com/cosmos/cosmos-sdk/tests" "github.com/cosmos/cosmos-sdk/types" @@ -43,7 +45,7 @@ func TestNewKeyring(t *testing.T) { require.Equal(t, "unknown keyring backend fuzzy", err.Error()) mockIn.Reset("password\npassword\n") - info, _, err := kr.NewMnemonic("foo", English, types.FullFundraiserPath, AltSecp256k1) + info, _, err := kr.NewMnemonic("foo", English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) require.Equal(t, "foo", info.GetName()) } @@ -54,7 +56,7 @@ func TestKeyManagementKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - algo := AltSecp256k1 + algo := salgo.AltSecp256k1 n1, n2, n3 := "personal", "business", "other" // Check empty state @@ -111,7 +113,7 @@ func TestKeyManagementKeyRing(t *testing.T) { o1 := "offline" priv1 := ed25519.GenPrivKey() pub1 := priv1.PubKey() - i, err = kb.SavePubKey(o1, pub1, Ed25519) + i, err = kb.SavePubKey(o1, pub1, salgo.Ed25519) require.Nil(t, err) require.Equal(t, pub1, i.GetPubKey()) require.Equal(t, o1, i.GetName()) @@ -138,7 +140,7 @@ func TestSignVerifyKeyRingWithLedger(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - i1, err := kb.SaveLedgerKey("key", AltSecp256k1, "cosmos", 118, 0, 0) + i1, err := kb.SaveLedgerKey("key", algo.AltSecp256k1, "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") @@ -159,7 +161,7 @@ func TestSignVerifyKeyRingWithLedger(t *testing.T) { require.True(t, i1.GetPubKey().VerifyBytes(d1, s1)) require.True(t, bytes.Equal(s1, s2)) - localInfo, _, err := kb.NewMnemonic("test", English, types.FullFundraiserPath, AltSecp256k1) + localInfo, _, err := kb.NewMnemonic("test", English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) _, _, err = SignWithLedger(localInfo, d1) require.Error(t, err) @@ -172,7 +174,7 @@ func TestSignVerifyKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - algo := AltSecp256k1 + algo := algo.AltSecp256k1 n1, n2, n3 := "some dude", "a dudette", "dude-ish" @@ -251,7 +253,7 @@ func TestExportImportKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, AltSecp256k1) + info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) require.Equal(t, info.GetName(), "john") @@ -284,7 +286,7 @@ func TestExportImportPubKeyKeyRing(t *testing.T) { t.Cleanup(cleanup) kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - algo := AltSecp256k1 + algo := algo.AltSecp256k1 // CreateMnemonic a private-public key pair and ensure consistency info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, algo) @@ -326,7 +328,7 @@ func TestAdvancedKeyManagementKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - algo := AltSecp256k1 + algo := algo.AltSecp256k1 n1, n2 := "old-name", "new name" // make sure key works with initial password @@ -361,7 +363,7 @@ func TestSeedPhraseKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - algo := AltSecp256k1 + algo := algo.AltSecp256k1 n1, n2 := "lost-key", "found-again" // make sure key works with initial password @@ -379,7 +381,7 @@ func TestSeedPhraseKeyRing(t *testing.T) { // let us re-create it from the mnemonic-phrase params := *hd.NewFundraiserParams(0, sdk.CoinType, 0) hdPath := params.String() - newInfo, err := kb.NewAccount(n2, mnemonic, DefaultBIP39Passphrase, hdPath, AltSecp256k1) + newInfo, err := kb.NewAccount(n2, mnemonic, DefaultBIP39Passphrase, hdPath, salgo.AltSecp256k1) require.NoError(t, err) require.Equal(t, n2, newInfo.GetName()) require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) @@ -392,7 +394,7 @@ func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - _, _, err = kb.NewMnemonic("john", English, types.FullFundraiserPath, AltSecp256k1) + _, _, err = kb.NewMnemonic("john", English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) keystr, err := kb.ExportPrivKeyArmor("john", "somepassword") @@ -419,7 +421,7 @@ func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { func TestInMemoryLanguage(t *testing.T) { kb := NewInMemory() - _, _, err := kb.NewMnemonic("something", Japanese, types.FullFundraiserPath, AltSecp256k1) + _, _, err := kb.NewMnemonic("something", Japanese, types.FullFundraiserPath, algo.AltSecp256k1) require.Error(t, err) require.Equal(t, "unsupported language: only english is supported", err.Error()) } @@ -440,7 +442,7 @@ func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { _, err := kb.NewAccount( "some_account", "malarkey pair crucial catch public canyon evil outer stage ten gym tornado", - "", hd.CreateHDPath(118, 0, 0).String(), AltSecp256k1) + "", hd.CreateHDPath(118, 0, 0).String(), algo.AltSecp256k1) require.Error(t, err) require.Equal(t, "Invalid mnemonic", err.Error()) } @@ -448,7 +450,7 @@ func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { func TestInMemoryCreateLedger(t *testing.T) { kb := NewInMemory() - ledger, err := kb.SaveLedgerKey("some_account", AltSecp256k1, "cosmos", 118, 3, 1) + ledger, err := kb.SaveLedgerKey("some_account", algo.AltSecp256k1, "cosmos", 118, 3, 1) if err != nil { require.Error(t, err) @@ -485,7 +487,7 @@ func TestInMemoryKeyManagement(t *testing.T) { // make the storage with reasonable defaults cstore := NewInMemory() - algo := AltSecp256k1 + algo := algo.AltSecp256k1 n1, n2, n3 := "personal", "business", "other" // Check empty state @@ -542,12 +544,12 @@ func TestInMemoryKeyManagement(t *testing.T) { o1 := "offline" priv1 := ed25519.GenPrivKey() pub1 := priv1.PubKey() - i, err = cstore.SavePubKey(o1, pub1, Ed25519) + i, err = cstore.SavePubKey(o1, pub1, salgo.Ed25519) require.Nil(t, err) require.Equal(t, pub1, i.GetPubKey()) require.Equal(t, o1, i.GetName()) iOffline := i.(*offlineInfo) - require.Equal(t, Ed25519, iOffline.GetAlgo()) + require.Equal(t, salgo.Ed25519, iOffline.GetAlgo()) keyS, err = cstore.List() require.NoError(t, err) require.Equal(t, 2, len(keyS)) @@ -568,7 +570,7 @@ func TestInMemoryKeyManagement(t *testing.T) { // signatures func TestInMemorySignVerify(t *testing.T) { cstore := NewInMemory() - algo := AltSecp256k1 + algo := algo.AltSecp256k1 n1, n2, n3 := "some dude", "a dudette", "dude-ish" @@ -647,7 +649,7 @@ func TestInMemoryExportImport(t *testing.T) { // make the storage with reasonable defaults cstore := NewInMemory() - info, _, err := cstore.NewMnemonic("john", English, types.FullFundraiserPath, AltSecp256k1) + info, _, err := cstore.NewMnemonic("john", English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) require.Equal(t, info.GetName(), "john") @@ -677,7 +679,7 @@ func TestInMemoryExportImport(t *testing.T) { func TestInMemoryExportImportPrivKey(t *testing.T) { kb := NewInMemory() - info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, AltSecp256k1) + info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) require.Equal(t, info.GetName(), "john") priv1, err := kb.Key("john") @@ -705,7 +707,7 @@ func TestInMemoryExportImportPubKey(t *testing.T) { cstore := NewInMemory() // CreateMnemonic a private-public key pair and ensure consistency - info, _, err := cstore.NewMnemonic("john", English, types.FullFundraiserPath, AltSecp256k1) + info, _, err := cstore.NewMnemonic("john", English, types.FullFundraiserPath, algo.AltSecp256k1) require.Nil(t, err) require.NotEqual(t, info, "") require.Equal(t, info.GetName(), "john") @@ -740,7 +742,7 @@ func TestInMemoryAdvancedKeyManagement(t *testing.T) { // make the storage with reasonable defaults cstore := NewInMemory() - algo := AltSecp256k1 + algo := algo.AltSecp256k1 n1, n2 := "old-name", "new name" // make sure key works with initial password @@ -775,7 +777,7 @@ func TestInMemorySeedPhrase(t *testing.T) { // make the storage with reasonable defaults cstore := NewInMemory() - algo := AltSecp256k1 + algo := algo.AltSecp256k1 n1, n2 := "lost-key", "found-again" // make sure key works with initial password @@ -808,17 +810,17 @@ func TestKeyChain_ShouldFailWhenAddingSameGeneratedAccount(t *testing.T) { require.NoError(t, err) // Given we create a mnemonic - _, seed, err := kr.NewMnemonic("test", English, "", AltSecp256k1) + _, seed, err := kr.NewMnemonic("test", English, "", algo.AltSecp256k1) require.NoError(t, err) require.NoError(t, kr.Delete("test")) path := hd.CreateHDPath(118, 0, 0).String() - _, err = kr.NewAccount("test1", seed, "", path, AltSecp256k1) + _, err = kr.NewAccount("test1", seed, "", path, algo.AltSecp256k1) require.NoError(t, err) // Creating another account with different uid but same seed should fail due to have same pub address - _, err = kr.NewAccount("test2", seed, "", path, AltSecp256k1) + _, err = kr.NewAccount("test2", seed, "", path, algo.AltSecp256k1) require.Error(t, err) } @@ -826,7 +828,7 @@ func ExampleNew() { // Select the encryption and storage for your cryptostore cstore := NewInMemory() - sec := AltSecp256k1 + sec := algo.AltSecp256k1 // Add keys and see they return in alphabetical order bob, _, err := cstore.NewMnemonic("Bob", English, types.FullFundraiserPath, sec) @@ -889,11 +891,11 @@ func TestAltKeyring_List(t *testing.T) { // Create 3 keys uid1, uid2, uid3 := "Zkey", "Bkey", "Rkey" - _, _, err = keyring.NewMnemonic(uid1, English, types.FullFundraiserPath, AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid1, English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) - _, _, err = keyring.NewMnemonic(uid2, English, types.FullFundraiserPath, AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid2, English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) - _, _, err = keyring.NewMnemonic(uid3, English, types.FullFundraiserPath, AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid3, English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) list, err = keyring.List() @@ -925,7 +927,7 @@ func TestAltKeyring_NewAccount(t *testing.T) { _, err = keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.FullFundraiserPath, notSupportedAlgo{}) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) - info, err := keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.FullFundraiserPath, AltSecp256k1) + info, err := keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) require.Equal(t, uid, info.GetName()) @@ -946,7 +948,7 @@ func TestAltKeyring_SaveLedgerKey(t *testing.T) { _, err = keyring.SaveLedgerKey("key", notSupportedAlgo{}, "cosmos", 118, 0, 0) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) - ledger, err := keyring.SaveLedgerKey("some_account", AltSecp256k1, "cosmos", 118, 3, 1) + ledger, err := keyring.SaveLedgerKey("some_account", algo.AltSecp256k1, "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") @@ -983,7 +985,7 @@ func TestAltKeyring_Get(t *testing.T) { require.NoError(t, err) uid := someKey - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) key, err := keyring.Key(uid) @@ -999,7 +1001,7 @@ func TestAltKeyring_KeyByAddress(t *testing.T) { require.NoError(t, err) uid := someKey - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) key, err := keyring.KeyByAddress(mnemonic.GetAddress()) @@ -1015,7 +1017,7 @@ func TestAltKeyring_Delete(t *testing.T) { require.NoError(t, err) uid := someKey - _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) list, err := keyring.List() @@ -1038,7 +1040,7 @@ func TestAltKeyring_DeleteByAddress(t *testing.T) { require.NoError(t, err) uid := someKey - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) list, err := keyring.List() @@ -1068,11 +1070,11 @@ func TestAltKeyring_SavePubKey(t *testing.T) { priv := ed25519.GenPrivKey() pub := priv.PubKey() - info, err := keyring.SavePubKey(key, pub, AltSecp256k1.Name()) + info, err := keyring.SavePubKey(key, pub, algo.AltSecp256k1.Name()) require.Nil(t, err) require.Equal(t, pub, info.GetPubKey()) require.Equal(t, key, info.GetName()) - require.Equal(t, AltSecp256k1.Name(), info.GetAlgo()) + require.Equal(t, algo.AltSecp256k1.Name(), info.GetAlgo()) list, err = keyring.List() require.NoError(t, err) @@ -1086,9 +1088,9 @@ func TestAltKeyring_SaveMultisig(t *testing.T) { keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - mnemonic1, _, err := keyring.NewMnemonic("key1", English, types.FullFundraiserPath, AltSecp256k1) + mnemonic1, _, err := keyring.NewMnemonic("key1", English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) - mnemonic2, _, err := keyring.NewMnemonic("key2", English, types.FullFundraiserPath, AltSecp256k1) + mnemonic2, _, err := keyring.NewMnemonic("key2", English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) key := "multi" @@ -1112,7 +1114,7 @@ func TestAltKeyring_Sign(t *testing.T) { require.NoError(t, err) uid := "jack" - _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) msg := []byte("some message") @@ -1131,7 +1133,7 @@ func TestAltKeyring_SignByAddress(t *testing.T) { require.NoError(t, err) uid := "jack" - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) msg := []byte("some message") @@ -1150,7 +1152,7 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { require.NoError(t, err) uid := theID - _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) passphrase := "somePass" @@ -1179,7 +1181,7 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { require.NoError(t, err) uid := theID - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) passphrase := "somePass" @@ -1210,7 +1212,7 @@ func TestAltKeyring_ImportExportPubKey(t *testing.T) { require.NoError(t, err) uid := theID - _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) armor, err := keyring.ExportPubKeyArmor(uid) @@ -1235,7 +1237,7 @@ func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { require.NoError(t, err) uid := theID - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, AltSecp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) armor, err := keyring.ExportPubKeyArmorByAddress(mnemonic.GetAddress()) @@ -1264,7 +1266,7 @@ func TestAltKeyring_ConstructorSupportedAlgos(t *testing.T) { require.EqualError(t, err, "unsupported signing algo") // but works with default signing algo. - _, _, err = keyring.NewMnemonic("test", English, types.FullFundraiserPath, AltSecp256k1) + _, _, err = keyring.NewMnemonic("test", English, types.FullFundraiserPath, algo.AltSecp256k1) require.NoError(t, err) // but we can create a new keybase with our provided algos. diff --git a/crypto/keyring/signing_algorithms.go b/crypto/keyring/signing_algorithms.go index d614404b937..9c620dc9d7b 100644 --- a/crypto/keyring/signing_algorithms.go +++ b/crypto/keyring/signing_algorithms.go @@ -3,63 +3,23 @@ package keyring import ( "fmt" - "github.com/cosmos/go-bip39" - "github.com/tendermint/tendermint/crypto" - tmcrypto "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/crypto/secp256k1" - - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" -) - -// pubKeyType defines an algorithm to derive key-pairs which can be used for cryptographic signing. -type pubKeyType string - -const ( - // MultiAlgo implies that a pubkey is a multisignature - MultiAlgo = pubKeyType("multi") - // Secp256k1 uses the Bitcoin secp256k1 ECDSA parameters. - Secp256k1 = pubKeyType("secp256k1") - // Ed25519 represents the Ed25519 signature system. - // It is currently not supported for end-user keys (wallets/ledgers). - Ed25519 = pubKeyType("ed25519") - // Sr25519 represents the Sr25519 signature system. - Sr25519 = pubKeyType("sr25519") + "github.com/cosmos/cosmos-sdk/crypto/algo" ) type SignatureAlgo interface { - Name() pubKeyType - DeriveKey() DeriveKeyFn - PrivKeyGen() PrivKeyGenFn + Name() algo.PubKeyType + DeriveKey() algo.DeriveKeyFn + PrivKeyGen() algo.PrivKeyGenFn } func NewSigningAlgoFromString(str string) (SignatureAlgo, error) { - if str != string(AltSecp256k1.Name()) { + if str != string(algo.AltSecp256k1.Name()) { return nil, fmt.Errorf("provided algorithm `%s` is not supported", str) } - return AltSecp256k1, nil -} - -type secp256k1Algo struct { -} - -func (s secp256k1Algo) Name() pubKeyType { - return Secp256k1 -} - -func (s secp256k1Algo) DeriveKey() DeriveKeyFn { - return Secp256k1DeriveKey -} - -func (s secp256k1Algo) PrivKeyGen() PrivKeyGenFn { - return Secp256k1PrivKeyGen + return algo.AltSecp256k1, nil } -var ( - // Secp256k1 uses the Bitcoin secp256k1 ECDSA parameters. - AltSecp256k1 = secp256k1Algo{} -) - type SigningAlgoList []SignatureAlgo func (l SigningAlgoList) Contains(algo SignatureAlgo) bool { @@ -71,28 +31,3 @@ func (l SigningAlgoList) Contains(algo SignatureAlgo) bool { return false } - -// Secp256k1PrivKeyGen generates a secp256k1 private key from the given bytes -func Secp256k1PrivKeyGen(bz []byte) tmcrypto.PrivKey { - var bzArr [32]byte - copy(bzArr[:], bz) - return secp256k1.PrivKeySecp256k1(bzArr) -} - -// Secp256k1DeriveKey derives and returns the secp256k1 private key for the given seed and HD path. -func Secp256k1DeriveKey(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) { - seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase) - if err != nil { - return nil, err - } - - masterPriv, ch := hd.ComputeMastersFromSeed(seed) - if len(hdPath) == 0 { - return masterPriv[:], nil - } - derivedKey, err := hd.DerivePrivateKeyForPath(masterPriv, ch, hdPath) - return derivedKey[:], err -} - -type DeriveKeyFn func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) -type PrivKeyGenFn func(bz []byte) crypto.PrivKey diff --git a/crypto/keyring/signing_algorithms_test.go b/crypto/keyring/signing_algorithms_test.go index 920323920ce..bff99c674c9 100644 --- a/crypto/keyring/signing_algorithms_test.go +++ b/crypto/keyring/signing_algorithms_test.go @@ -4,16 +4,18 @@ import ( "fmt" "testing" + "github.com/cosmos/cosmos-sdk/crypto/algo" + "github.com/stretchr/testify/require" "github.com/stretchr/testify/assert" ) func TestDefaults(t *testing.T) { - require.Equal(t, pubKeyType("multi"), MultiAlgo) - require.Equal(t, pubKeyType("secp256k1"), Secp256k1) - require.Equal(t, pubKeyType("ed25519"), Ed25519) - require.Equal(t, pubKeyType("sr25519"), Sr25519) + require.Equal(t, algo.PubKeyType("multi"), algo.MultiAlgo) + require.Equal(t, algo.PubKeyType("secp256k1"), algo.Secp256k1) + require.Equal(t, algo.PubKeyType("ed25519"), algo.Ed25519) + require.Equal(t, algo.PubKeyType("sr25519"), algo.Sr25519) } func TestNewSigningAlgoByString(t *testing.T) { @@ -28,7 +30,7 @@ func TestNewSigningAlgoByString(t *testing.T) { "supported algorithm", "secp256k1", true, - AltSecp256k1, + algo.AltSecp256k1, nil, }, { @@ -42,9 +44,9 @@ func TestNewSigningAlgoByString(t *testing.T) { for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { - algo, err := NewSigningAlgoFromString(tt.algoStr) + algorithm, err := NewSigningAlgoFromString(tt.algoStr) if tt.isSupported { - require.Equal(t, AltSecp256k1, algo) + require.Equal(t, algo.AltSecp256k1, algorithm) } else { require.EqualError(t, err, tt.expectedErr.Error()) } @@ -54,24 +56,24 @@ func TestNewSigningAlgoByString(t *testing.T) { func TestAltSigningAlgoList_Contains(t *testing.T) { list := SigningAlgoList{ - AltSecp256k1, + algo.AltSecp256k1, } - assert.True(t, list.Contains(AltSecp256k1)) + assert.True(t, list.Contains(algo.AltSecp256k1)) assert.False(t, list.Contains(notSupportedAlgo{})) } type notSupportedAlgo struct { } -func (n notSupportedAlgo) Name() pubKeyType { +func (n notSupportedAlgo) Name() algo.PubKeyType { return "notSupported" } -func (n notSupportedAlgo) DeriveKey() DeriveKeyFn { - return Secp256k1DeriveKey +func (n notSupportedAlgo) DeriveKey() algo.DeriveKeyFn { + return algo.Secp256k1DeriveKey } -func (n notSupportedAlgo) PrivKeyGen() PrivKeyGenFn { - return Secp256k1PrivKeyGen +func (n notSupportedAlgo) PrivKeyGen() algo.PrivKeyGenFn { + return algo.Secp256k1PrivKeyGen } diff --git a/crypto/keyring/types.go b/crypto/keyring/types.go index 0e48d9cdbab..d4c5bdbad47 100644 --- a/crypto/keyring/types.go +++ b/crypto/keyring/types.go @@ -1,6 +1,9 @@ package keyring -import "github.com/tendermint/tendermint/crypto" +import ( + "github.com/cosmos/cosmos-sdk/crypto/algo" + "github.com/tendermint/tendermint/crypto" +) // Language is a language to create the BIP 39 mnemonic in. // Currently, only english is supported though. @@ -62,7 +65,7 @@ func (kt KeyType) String() string { type ( // DeriveKeyFunc defines the function to derive a new key from a seed and hd path - DeriveKeyFunc func(mnemonic string, bip39Passphrase, hdPath string, algo pubKeyType) ([]byte, error) + DeriveKeyFunc func(mnemonic string, bip39Passphrase, hdPath string, algo algo.PubKeyType) ([]byte, error) // PrivKeyGenFunc defines the function to convert derived key bytes to a tendermint private key - PrivKeyGenFunc func(bz []byte, algo pubKeyType) (crypto.PrivKey, error) + PrivKeyGenFunc func(bz []byte, algo algo.PubKeyType) (crypto.PrivKey, error) ) diff --git a/crypto/keyring/types_test.go b/crypto/keyring/types_test.go index c2cb9723c2c..6d26f298c9b 100644 --- a/crypto/keyring/types_test.go +++ b/crypto/keyring/types_test.go @@ -2,6 +2,7 @@ package keyring import ( "encoding/hex" + "github.com/cosmos/cosmos-sdk/crypto/algo" "testing" "github.com/stretchr/testify/assert" @@ -16,7 +17,7 @@ func Test_writeReadLedgerInfo(t *testing.T) { bz, _ := hex.DecodeString("035AD6810A47F073553FF30D2FCC7E0D3B1C0B74B61A1AAA2582344037151E143A") copy(tmpKey[:], bz) - lInfo := newLedgerInfo("some_name", tmpKey, *hd.NewFundraiserParams(5, sdk.CoinType, 1), Secp256k1) + lInfo := newLedgerInfo("some_name", tmpKey, *hd.NewFundraiserParams(5, sdk.CoinType, 1), algo.Secp256k1) assert.Equal(t, TypeLedger, lInfo.GetType()) path, err := lInfo.GetPath() diff --git a/server/init.go b/server/init.go index a55b8acd366..dc3db47e60e 100644 --- a/server/init.go +++ b/server/init.go @@ -2,6 +2,7 @@ package server import ( "fmt" + "github.com/cosmos/cosmos-sdk/crypto/algo" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/types" @@ -13,7 +14,7 @@ import ( // phrase to recover the private key. func GenerateCoinKey() (sdk.AccAddress, string, error) { // generate a private key, with recovery phrase - info, secret, err := keyring.NewInMemory().NewMnemonic("name", keyring.English, types.FullFundraiserPath, keyring.AltSecp256k1) + info, secret, err := keyring.NewInMemory().NewMnemonic("name", keyring.English, types.FullFundraiserPath, algo.AltSecp256k1) if err != nil { return sdk.AccAddress([]byte{}), "", err } @@ -33,7 +34,7 @@ func GenerateSaveCoinKey(keybase keyring.Keyring, keyName, keyPass string, overw } // generate a private key, with recovery phrase - info, secret, err := keybase.NewMnemonic(keyName, keyring.English, types.FullFundraiserPath, keyring.AltSecp256k1) + info, secret, err := keybase.NewMnemonic(keyName, keyring.English, types.FullFundraiserPath, algo.AltSecp256k1) if err != nil { return sdk.AccAddress([]byte{}), "", err } diff --git a/server/init_test.go b/server/init_test.go index 1828e2aedbb..a45cd6b240c 100644 --- a/server/init_test.go +++ b/server/init_test.go @@ -1,6 +1,7 @@ package server_test import ( + "github.com/cosmos/cosmos-sdk/crypto/algo" "testing" "github.com/stretchr/testify/require" @@ -18,7 +19,7 @@ func TestGenerateCoinKey(t *testing.T) { require.NoError(t, err) // Test creation - info, err := keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), keyring.AltSecp256k1) + info, err := keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), algo.AltSecp256k1) require.NoError(t, err) require.Equal(t, addr, info.GetAddress()) } @@ -40,7 +41,7 @@ func TestGenerateSaveCoinKey(t *testing.T) { require.Equal(t, addr, info.GetAddress()) // Test in-memory recovery - info, err = keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), keyring.AltSecp256k1) + info, err = keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), algo.AltSecp256k1) require.NoError(t, err) require.Equal(t, addr, info.GetAddress()) } From df54d24df90084f323d5800fe3ab3d5a624416dc Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 3 Apr 2020 23:35:02 +0200 Subject: [PATCH 120/148] refactor naming --- client/keys/add.go | 6 +- client/keys/delete_test.go | 4 +- client/keys/export_test.go | 2 +- client/keys/list_test.go | 2 +- client/keys/show_test.go | 4 +- crypto/algo/algo.go | 28 +++---- crypto/armor_test.go | 6 +- crypto/keyring/info.go | 2 +- crypto/keyring/keyring.go | 4 +- crypto/keyring/keyring_test.go | 96 +++++++++++------------ crypto/keyring/signing_algorithms.go | 4 +- crypto/keyring/signing_algorithms_test.go | 16 ++-- crypto/keyring/types_test.go | 2 +- server/init.go | 4 +- server/init_test.go | 4 +- 15 files changed, 92 insertions(+), 92 deletions(-) diff --git a/client/keys/add.go b/client/keys/add.go index 3c2bc02fdda..c3b2eb21b1f 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -80,7 +80,7 @@ the flag --nosort is set. cmd.Flags().Uint32(flagAccount, 0, "Account number for HD derivation") cmd.Flags().Uint32(flagIndex, 0, "Address index number for HD derivation") cmd.Flags().Bool(flags.FlagIndentResponse, false, "Add indent to JSON response") - cmd.Flags().String(flagKeyAlgo, string(algo2.Secp256k1), "Key signing algorithm to generate keys for") + cmd.Flags().String(flagKeyAlgo, string(algo2.Secp256k1Type), "Key signing algorithm to generate keys for") return cmd } @@ -121,7 +121,7 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *buf algo, err := keyring.NewSigningAlgoFromString(viper.GetString(flagKeyAlgo)) if err != nil { - algo = algo2.AltSecp256k1 + algo = algo2.Secp256k1 } if !viper.GetBool(flags.FlagDryRun) { @@ -204,7 +204,7 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *buf } bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix() - info, err := kb.SaveLedgerKey(name, algo2.AltSecp256k1, bech32PrefixAccAddr, coinType, account, index) + info, err := kb.SaveLedgerKey(name, algo2.Secp256k1, bech32PrefixAccAddr, coinType, account, index) if err != nil { return err } diff --git a/client/keys/delete_test.go b/client/keys/delete_test.go index 71d2e4bb18c..8eaf59fbdd7 100644 --- a/client/keys/delete_test.go +++ b/client/keys/delete_test.go @@ -35,9 +35,9 @@ func Test_runDeleteCmd(t *testing.T) { backend := viper.GetString(flags.FlagKeyringBackend) kb, err := keyring.New(sdk.KeyringServiceName(), backend, kbHome, mockIn) require.NoError(t, err) - _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, algo.AltSecp256k1) + _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, algo.Secp256k1) require.NoError(t, err) - _, _, err = kb.NewMnemonic(fakeKeyName2, keyring.English, sdk.FullFundraiserPath, algo.AltSecp256k1) + _, _, err = kb.NewMnemonic(fakeKeyName2, keyring.English, sdk.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) err = runDeleteCmd(deleteKeyCommand, []string{"blah"}) diff --git a/client/keys/export_test.go b/client/keys/export_test.go index 9ffa6615efc..7eafaaaf5a1 100644 --- a/client/keys/export_test.go +++ b/client/keys/export_test.go @@ -30,7 +30,7 @@ func Test_runExportCmd(t *testing.T) { }) path := sdk.GetConfig().GetFullFundraiserPath() - _, err = kb.NewAccount("keyname1", tests.TestMnemonic, "", path, algo.AltSecp256k1) + _, err = kb.NewAccount("keyname1", tests.TestMnemonic, "", path, algo.Secp256k1) require.NoError(t, err) // Now enter password diff --git a/client/keys/list_test.go b/client/keys/list_test.go index bd01bcc57e4..529748dc068 100644 --- a/client/keys/list_test.go +++ b/client/keys/list_test.go @@ -36,7 +36,7 @@ func Test_runListCmd(t *testing.T) { require.NoError(t, err) path := "" //sdk.GetConfig().GetFullFundraiserPath() - _, err = kb.NewAccount("something", tests.TestMnemonic, "", path, algo.AltSecp256k1) + _, err = kb.NewAccount("something", tests.TestMnemonic, "", path, algo.Secp256k1) require.NoError(t, err) t.Cleanup(func() { diff --git a/client/keys/show_test.go b/client/keys/show_test.go index 00ba7c03aec..86139e2e015 100644 --- a/client/keys/show_test.go +++ b/client/keys/show_test.go @@ -58,10 +58,10 @@ func Test_runShowCmd(t *testing.T) { }) path := hd.NewFundraiserParams(1, sdk.CoinType, 0).String() - _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, algo.AltSecp256k1) + _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, algo.Secp256k1) require.NoError(t, err) - _, err = kb.NewAccount(fakeKeyName2, tests.TestMnemonic, "", path, algo.AltSecp256k1) + _, err = kb.NewAccount(fakeKeyName2, tests.TestMnemonic, "", path, algo.Secp256k1) require.NoError(t, err) // Now try single key diff --git a/crypto/algo/algo.go b/crypto/algo/algo.go index beb7fd61c20..b390164a98c 100644 --- a/crypto/algo/algo.go +++ b/crypto/algo/algo.go @@ -12,15 +12,20 @@ import ( type PubKeyType string const ( - // MultiAlgo implies that a pubkey is a multisignature - MultiAlgo = PubKeyType("multi") - // Secp256k1 uses the Bitcoin secp256k1 ECDSA parameters. - Secp256k1 = PubKeyType("secp256k1") - // Ed25519 represents the Ed25519 signature system. + // MultiType implies that a pubkey is a multisignature + MultiType = PubKeyType("multi") + // Secp256k1Type uses the Bitcoin secp256k1 ECDSA parameters. + Secp256k1Type = PubKeyType("secp256k1") + // Ed25519Type represents the Ed25519Type signature system. // It is currently not supported for end-user keys (wallets/ledgers). - Ed25519 = PubKeyType("ed25519") - // Sr25519 represents the Sr25519 signature system. - Sr25519 = PubKeyType("sr25519") + Ed25519Type = PubKeyType("ed25519") + // Sr25519Type represents the Sr25519Type signature system. + Sr25519Type = PubKeyType("sr25519") +) + +var ( + // Secp256k1 uses the Bitcoin secp256k1 ECDSA parameters. + Secp256k1 = secp256k1Algo{} ) type DeriveKeyFn func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) @@ -30,7 +35,7 @@ type secp256k1Algo struct { } func (s secp256k1Algo) Name() PubKeyType { - return Secp256k1 + return Secp256k1Type } func (s secp256k1Algo) DeriveKey() DeriveKeyFn { @@ -41,11 +46,6 @@ func (s secp256k1Algo) PrivKeyGen() PrivKeyGenFn { return Secp256k1PrivKeyGen } -var ( - // Secp256k1 uses the Bitcoin secp256k1 ECDSA parameters. - AltSecp256k1 = secp256k1Algo{} -) - // Secp256k1PrivKeyGen generates a secp256k1 private key from the given bytes func Secp256k1PrivKeyGen(bz []byte) crypto.PrivKey { var bzArr [32]byte diff --git a/crypto/armor_test.go b/crypto/armor_test.go index ebcc657231f..315ea435d39 100644 --- a/crypto/armor_test.go +++ b/crypto/armor_test.go @@ -28,7 +28,7 @@ func TestArmorUnarmorPrivKey(t *testing.T) { require.Error(t, err) decrypted, algo, err := crypto.UnarmorDecryptPrivKey(armored, "passphrase") require.NoError(t, err) - require.Equal(t, string(algo2.Secp256k1), algo) + require.Equal(t, string(algo2.Secp256k1Type), algo) require.True(t, priv.Equals(decrypted)) // empty string @@ -72,14 +72,14 @@ func TestArmorUnarmorPubKey(t *testing.T) { cstore := keyring.NewInMemory() // Add keys and see they return in alphabetical order - info, _, err := cstore.NewMnemonic("Bob", keyring.English, types.FullFundraiserPath, algo2.AltSecp256k1) + info, _, err := cstore.NewMnemonic("Bob", keyring.English, types.FullFundraiserPath, algo2.Secp256k1) require.NoError(t, err) armored := crypto.ArmorPubKeyBytes(info.GetPubKey().Bytes(), "") pubBytes, algo, err := crypto.UnarmorPubKeyBytes(armored) require.NoError(t, err) pub, err := cryptoAmino.PubKeyFromBytes(pubBytes) require.NoError(t, err) - require.Equal(t, string(algo2.Secp256k1), algo) + require.Equal(t, string(algo2.Secp256k1Type), algo) require.True(t, pub.Equals(info.GetPubKey())) armored = crypto.ArmorPubKeyBytes(info.GetPubKey().Bytes(), "unknown") diff --git a/crypto/keyring/info.go b/crypto/keyring/info.go index db1966a9810..d2778a8eb71 100644 --- a/crypto/keyring/info.go +++ b/crypto/keyring/info.go @@ -231,7 +231,7 @@ func (i multiInfo) GetAddress() types.AccAddress { // GetPath implements Info interface func (i multiInfo) GetAlgo() algo.PubKeyType { - return algo.MultiAlgo + return algo.MultiType } // GetPath implements Info interface diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index a792a9cec94..61fddff63a8 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -158,8 +158,8 @@ type keystore struct { func newKeystore(kr keyring.Keyring, opts ...Option) keystore { // Default options for keybase options := Options{ - SupportedAlgos: SigningAlgoList{salgo.AltSecp256k1}, - SupportedAlgosLedger: SigningAlgoList{salgo.AltSecp256k1}, + SupportedAlgos: SigningAlgoList{salgo.Secp256k1}, + SupportedAlgosLedger: SigningAlgoList{salgo.Secp256k1}, } for _, optionFn := range opts { diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 2e6a873979b..bb2c934b068 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -45,7 +45,7 @@ func TestNewKeyring(t *testing.T) { require.Equal(t, "unknown keyring backend fuzzy", err.Error()) mockIn.Reset("password\npassword\n") - info, _, err := kr.NewMnemonic("foo", English, types.FullFundraiserPath, algo.AltSecp256k1) + info, _, err := kr.NewMnemonic("foo", English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) require.Equal(t, "foo", info.GetName()) } @@ -56,7 +56,7 @@ func TestKeyManagementKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - algo := salgo.AltSecp256k1 + algo := salgo.Secp256k1 n1, n2, n3 := "personal", "business", "other" // Check empty state @@ -113,7 +113,7 @@ func TestKeyManagementKeyRing(t *testing.T) { o1 := "offline" priv1 := ed25519.GenPrivKey() pub1 := priv1.PubKey() - i, err = kb.SavePubKey(o1, pub1, salgo.Ed25519) + i, err = kb.SavePubKey(o1, pub1, salgo.Ed25519Type) require.Nil(t, err) require.Equal(t, pub1, i.GetPubKey()) require.Equal(t, o1, i.GetName()) @@ -140,7 +140,7 @@ func TestSignVerifyKeyRingWithLedger(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - i1, err := kb.SaveLedgerKey("key", algo.AltSecp256k1, "cosmos", 118, 0, 0) + i1, err := kb.SaveLedgerKey("key", algo.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") @@ -161,7 +161,7 @@ func TestSignVerifyKeyRingWithLedger(t *testing.T) { require.True(t, i1.GetPubKey().VerifyBytes(d1, s1)) require.True(t, bytes.Equal(s1, s2)) - localInfo, _, err := kb.NewMnemonic("test", English, types.FullFundraiserPath, algo.AltSecp256k1) + localInfo, _, err := kb.NewMnemonic("test", English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) _, _, err = SignWithLedger(localInfo, d1) require.Error(t, err) @@ -174,7 +174,7 @@ func TestSignVerifyKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - algo := algo.AltSecp256k1 + algo := algo.Secp256k1 n1, n2, n3 := "some dude", "a dudette", "dude-ish" @@ -253,7 +253,7 @@ func TestExportImportKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, algo.AltSecp256k1) + info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) require.Equal(t, info.GetName(), "john") @@ -286,7 +286,7 @@ func TestExportImportPubKeyKeyRing(t *testing.T) { t.Cleanup(cleanup) kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - algo := algo.AltSecp256k1 + algo := algo.Secp256k1 // CreateMnemonic a private-public key pair and ensure consistency info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, algo) @@ -328,7 +328,7 @@ func TestAdvancedKeyManagementKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - algo := algo.AltSecp256k1 + algo := algo.Secp256k1 n1, n2 := "old-name", "new name" // make sure key works with initial password @@ -363,7 +363,7 @@ func TestSeedPhraseKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - algo := algo.AltSecp256k1 + algo := algo.Secp256k1 n1, n2 := "lost-key", "found-again" // make sure key works with initial password @@ -381,7 +381,7 @@ func TestSeedPhraseKeyRing(t *testing.T) { // let us re-create it from the mnemonic-phrase params := *hd.NewFundraiserParams(0, sdk.CoinType, 0) hdPath := params.String() - newInfo, err := kb.NewAccount(n2, mnemonic, DefaultBIP39Passphrase, hdPath, salgo.AltSecp256k1) + newInfo, err := kb.NewAccount(n2, mnemonic, DefaultBIP39Passphrase, hdPath, salgo.Secp256k1) require.NoError(t, err) require.Equal(t, n2, newInfo.GetName()) require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) @@ -394,7 +394,7 @@ func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - _, _, err = kb.NewMnemonic("john", English, types.FullFundraiserPath, algo.AltSecp256k1) + _, _, err = kb.NewMnemonic("john", English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) keystr, err := kb.ExportPrivKeyArmor("john", "somepassword") @@ -421,7 +421,7 @@ func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { func TestInMemoryLanguage(t *testing.T) { kb := NewInMemory() - _, _, err := kb.NewMnemonic("something", Japanese, types.FullFundraiserPath, algo.AltSecp256k1) + _, _, err := kb.NewMnemonic("something", Japanese, types.FullFundraiserPath, algo.Secp256k1) require.Error(t, err) require.Equal(t, "unsupported language: only english is supported", err.Error()) } @@ -442,7 +442,7 @@ func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { _, err := kb.NewAccount( "some_account", "malarkey pair crucial catch public canyon evil outer stage ten gym tornado", - "", hd.CreateHDPath(118, 0, 0).String(), algo.AltSecp256k1) + "", hd.CreateHDPath(118, 0, 0).String(), algo.Secp256k1) require.Error(t, err) require.Equal(t, "Invalid mnemonic", err.Error()) } @@ -450,7 +450,7 @@ func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { func TestInMemoryCreateLedger(t *testing.T) { kb := NewInMemory() - ledger, err := kb.SaveLedgerKey("some_account", algo.AltSecp256k1, "cosmos", 118, 3, 1) + ledger, err := kb.SaveLedgerKey("some_account", algo.Secp256k1, "cosmos", 118, 3, 1) if err != nil { require.Error(t, err) @@ -487,7 +487,7 @@ func TestInMemoryKeyManagement(t *testing.T) { // make the storage with reasonable defaults cstore := NewInMemory() - algo := algo.AltSecp256k1 + algo := algo.Secp256k1 n1, n2, n3 := "personal", "business", "other" // Check empty state @@ -544,12 +544,12 @@ func TestInMemoryKeyManagement(t *testing.T) { o1 := "offline" priv1 := ed25519.GenPrivKey() pub1 := priv1.PubKey() - i, err = cstore.SavePubKey(o1, pub1, salgo.Ed25519) + i, err = cstore.SavePubKey(o1, pub1, salgo.Ed25519Type) require.Nil(t, err) require.Equal(t, pub1, i.GetPubKey()) require.Equal(t, o1, i.GetName()) iOffline := i.(*offlineInfo) - require.Equal(t, salgo.Ed25519, iOffline.GetAlgo()) + require.Equal(t, salgo.Ed25519Type, iOffline.GetAlgo()) keyS, err = cstore.List() require.NoError(t, err) require.Equal(t, 2, len(keyS)) @@ -570,7 +570,7 @@ func TestInMemoryKeyManagement(t *testing.T) { // signatures func TestInMemorySignVerify(t *testing.T) { cstore := NewInMemory() - algo := algo.AltSecp256k1 + algo := algo.Secp256k1 n1, n2, n3 := "some dude", "a dudette", "dude-ish" @@ -649,7 +649,7 @@ func TestInMemoryExportImport(t *testing.T) { // make the storage with reasonable defaults cstore := NewInMemory() - info, _, err := cstore.NewMnemonic("john", English, types.FullFundraiserPath, algo.AltSecp256k1) + info, _, err := cstore.NewMnemonic("john", English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) require.Equal(t, info.GetName(), "john") @@ -679,7 +679,7 @@ func TestInMemoryExportImport(t *testing.T) { func TestInMemoryExportImportPrivKey(t *testing.T) { kb := NewInMemory() - info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, algo.AltSecp256k1) + info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) require.Equal(t, info.GetName(), "john") priv1, err := kb.Key("john") @@ -707,7 +707,7 @@ func TestInMemoryExportImportPubKey(t *testing.T) { cstore := NewInMemory() // CreateMnemonic a private-public key pair and ensure consistency - info, _, err := cstore.NewMnemonic("john", English, types.FullFundraiserPath, algo.AltSecp256k1) + info, _, err := cstore.NewMnemonic("john", English, types.FullFundraiserPath, algo.Secp256k1) require.Nil(t, err) require.NotEqual(t, info, "") require.Equal(t, info.GetName(), "john") @@ -742,7 +742,7 @@ func TestInMemoryAdvancedKeyManagement(t *testing.T) { // make the storage with reasonable defaults cstore := NewInMemory() - algo := algo.AltSecp256k1 + algo := algo.Secp256k1 n1, n2 := "old-name", "new name" // make sure key works with initial password @@ -777,7 +777,7 @@ func TestInMemorySeedPhrase(t *testing.T) { // make the storage with reasonable defaults cstore := NewInMemory() - algo := algo.AltSecp256k1 + algo := algo.Secp256k1 n1, n2 := "lost-key", "found-again" // make sure key works with initial password @@ -810,17 +810,17 @@ func TestKeyChain_ShouldFailWhenAddingSameGeneratedAccount(t *testing.T) { require.NoError(t, err) // Given we create a mnemonic - _, seed, err := kr.NewMnemonic("test", English, "", algo.AltSecp256k1) + _, seed, err := kr.NewMnemonic("test", English, "", algo.Secp256k1) require.NoError(t, err) require.NoError(t, kr.Delete("test")) path := hd.CreateHDPath(118, 0, 0).String() - _, err = kr.NewAccount("test1", seed, "", path, algo.AltSecp256k1) + _, err = kr.NewAccount("test1", seed, "", path, algo.Secp256k1) require.NoError(t, err) // Creating another account with different uid but same seed should fail due to have same pub address - _, err = kr.NewAccount("test2", seed, "", path, algo.AltSecp256k1) + _, err = kr.NewAccount("test2", seed, "", path, algo.Secp256k1) require.Error(t, err) } @@ -828,7 +828,7 @@ func ExampleNew() { // Select the encryption and storage for your cryptostore cstore := NewInMemory() - sec := algo.AltSecp256k1 + sec := algo.Secp256k1 // Add keys and see they return in alphabetical order bob, _, err := cstore.NewMnemonic("Bob", English, types.FullFundraiserPath, sec) @@ -891,11 +891,11 @@ func TestAltKeyring_List(t *testing.T) { // Create 3 keys uid1, uid2, uid3 := "Zkey", "Bkey", "Rkey" - _, _, err = keyring.NewMnemonic(uid1, English, types.FullFundraiserPath, algo.AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid1, English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) - _, _, err = keyring.NewMnemonic(uid2, English, types.FullFundraiserPath, algo.AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid2, English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) - _, _, err = keyring.NewMnemonic(uid3, English, types.FullFundraiserPath, algo.AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid3, English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) list, err = keyring.List() @@ -927,7 +927,7 @@ func TestAltKeyring_NewAccount(t *testing.T) { _, err = keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.FullFundraiserPath, notSupportedAlgo{}) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) - info, err := keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.FullFundraiserPath, algo.AltSecp256k1) + info, err := keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) require.Equal(t, uid, info.GetName()) @@ -948,7 +948,7 @@ func TestAltKeyring_SaveLedgerKey(t *testing.T) { _, err = keyring.SaveLedgerKey("key", notSupportedAlgo{}, "cosmos", 118, 0, 0) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) - ledger, err := keyring.SaveLedgerKey("some_account", algo.AltSecp256k1, "cosmos", 118, 3, 1) + ledger, err := keyring.SaveLedgerKey("some_account", algo.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") @@ -985,7 +985,7 @@ func TestAltKeyring_Get(t *testing.T) { require.NoError(t, err) uid := someKey - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) key, err := keyring.Key(uid) @@ -1001,7 +1001,7 @@ func TestAltKeyring_KeyByAddress(t *testing.T) { require.NoError(t, err) uid := someKey - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) key, err := keyring.KeyByAddress(mnemonic.GetAddress()) @@ -1017,7 +1017,7 @@ func TestAltKeyring_Delete(t *testing.T) { require.NoError(t, err) uid := someKey - _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) list, err := keyring.List() @@ -1040,7 +1040,7 @@ func TestAltKeyring_DeleteByAddress(t *testing.T) { require.NoError(t, err) uid := someKey - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) list, err := keyring.List() @@ -1070,11 +1070,11 @@ func TestAltKeyring_SavePubKey(t *testing.T) { priv := ed25519.GenPrivKey() pub := priv.PubKey() - info, err := keyring.SavePubKey(key, pub, algo.AltSecp256k1.Name()) + info, err := keyring.SavePubKey(key, pub, algo.Secp256k1.Name()) require.Nil(t, err) require.Equal(t, pub, info.GetPubKey()) require.Equal(t, key, info.GetName()) - require.Equal(t, algo.AltSecp256k1.Name(), info.GetAlgo()) + require.Equal(t, algo.Secp256k1.Name(), info.GetAlgo()) list, err = keyring.List() require.NoError(t, err) @@ -1088,9 +1088,9 @@ func TestAltKeyring_SaveMultisig(t *testing.T) { keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - mnemonic1, _, err := keyring.NewMnemonic("key1", English, types.FullFundraiserPath, algo.AltSecp256k1) + mnemonic1, _, err := keyring.NewMnemonic("key1", English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) - mnemonic2, _, err := keyring.NewMnemonic("key2", English, types.FullFundraiserPath, algo.AltSecp256k1) + mnemonic2, _, err := keyring.NewMnemonic("key2", English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) key := "multi" @@ -1114,7 +1114,7 @@ func TestAltKeyring_Sign(t *testing.T) { require.NoError(t, err) uid := "jack" - _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) msg := []byte("some message") @@ -1133,7 +1133,7 @@ func TestAltKeyring_SignByAddress(t *testing.T) { require.NoError(t, err) uid := "jack" - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) msg := []byte("some message") @@ -1152,7 +1152,7 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { require.NoError(t, err) uid := theID - _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) passphrase := "somePass" @@ -1181,7 +1181,7 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { require.NoError(t, err) uid := theID - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) passphrase := "somePass" @@ -1212,7 +1212,7 @@ func TestAltKeyring_ImportExportPubKey(t *testing.T) { require.NoError(t, err) uid := theID - _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) armor, err := keyring.ExportPubKeyArmor(uid) @@ -1237,7 +1237,7 @@ func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { require.NoError(t, err) uid := theID - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.AltSecp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) armor, err := keyring.ExportPubKeyArmorByAddress(mnemonic.GetAddress()) @@ -1266,7 +1266,7 @@ func TestAltKeyring_ConstructorSupportedAlgos(t *testing.T) { require.EqualError(t, err, "unsupported signing algo") // but works with default signing algo. - _, _, err = keyring.NewMnemonic("test", English, types.FullFundraiserPath, algo.AltSecp256k1) + _, _, err = keyring.NewMnemonic("test", English, types.FullFundraiserPath, algo.Secp256k1) require.NoError(t, err) // but we can create a new keybase with our provided algos. diff --git a/crypto/keyring/signing_algorithms.go b/crypto/keyring/signing_algorithms.go index 9c620dc9d7b..5a17384044e 100644 --- a/crypto/keyring/signing_algorithms.go +++ b/crypto/keyring/signing_algorithms.go @@ -13,11 +13,11 @@ type SignatureAlgo interface { } func NewSigningAlgoFromString(str string) (SignatureAlgo, error) { - if str != string(algo.AltSecp256k1.Name()) { + if str != string(algo.Secp256k1.Name()) { return nil, fmt.Errorf("provided algorithm `%s` is not supported", str) } - return algo.AltSecp256k1, nil + return algo.Secp256k1, nil } type SigningAlgoList []SignatureAlgo diff --git a/crypto/keyring/signing_algorithms_test.go b/crypto/keyring/signing_algorithms_test.go index bff99c674c9..0acd18b8034 100644 --- a/crypto/keyring/signing_algorithms_test.go +++ b/crypto/keyring/signing_algorithms_test.go @@ -12,10 +12,10 @@ import ( ) func TestDefaults(t *testing.T) { - require.Equal(t, algo.PubKeyType("multi"), algo.MultiAlgo) - require.Equal(t, algo.PubKeyType("secp256k1"), algo.Secp256k1) - require.Equal(t, algo.PubKeyType("ed25519"), algo.Ed25519) - require.Equal(t, algo.PubKeyType("sr25519"), algo.Sr25519) + require.Equal(t, algo.PubKeyType("multi"), algo.MultiType) + require.Equal(t, algo.PubKeyType("secp256k1"), algo.Secp256k1Type) + require.Equal(t, algo.PubKeyType("ed25519"), algo.Ed25519Type) + require.Equal(t, algo.PubKeyType("sr25519"), algo.Sr25519Type) } func TestNewSigningAlgoByString(t *testing.T) { @@ -30,7 +30,7 @@ func TestNewSigningAlgoByString(t *testing.T) { "supported algorithm", "secp256k1", true, - algo.AltSecp256k1, + algo.Secp256k1, nil, }, { @@ -46,7 +46,7 @@ func TestNewSigningAlgoByString(t *testing.T) { t.Run(tt.name, func(t *testing.T) { algorithm, err := NewSigningAlgoFromString(tt.algoStr) if tt.isSupported { - require.Equal(t, algo.AltSecp256k1, algorithm) + require.Equal(t, algo.Secp256k1, algorithm) } else { require.EqualError(t, err, tt.expectedErr.Error()) } @@ -56,10 +56,10 @@ func TestNewSigningAlgoByString(t *testing.T) { func TestAltSigningAlgoList_Contains(t *testing.T) { list := SigningAlgoList{ - algo.AltSecp256k1, + algo.Secp256k1, } - assert.True(t, list.Contains(algo.AltSecp256k1)) + assert.True(t, list.Contains(algo.Secp256k1)) assert.False(t, list.Contains(notSupportedAlgo{})) } diff --git a/crypto/keyring/types_test.go b/crypto/keyring/types_test.go index 6d26f298c9b..61fec4437e2 100644 --- a/crypto/keyring/types_test.go +++ b/crypto/keyring/types_test.go @@ -17,7 +17,7 @@ func Test_writeReadLedgerInfo(t *testing.T) { bz, _ := hex.DecodeString("035AD6810A47F073553FF30D2FCC7E0D3B1C0B74B61A1AAA2582344037151E143A") copy(tmpKey[:], bz) - lInfo := newLedgerInfo("some_name", tmpKey, *hd.NewFundraiserParams(5, sdk.CoinType, 1), algo.Secp256k1) + lInfo := newLedgerInfo("some_name", tmpKey, *hd.NewFundraiserParams(5, sdk.CoinType, 1), algo.Secp256k1Type) assert.Equal(t, TypeLedger, lInfo.GetType()) path, err := lInfo.GetPath() diff --git a/server/init.go b/server/init.go index dc3db47e60e..19c2ec057fe 100644 --- a/server/init.go +++ b/server/init.go @@ -14,7 +14,7 @@ import ( // phrase to recover the private key. func GenerateCoinKey() (sdk.AccAddress, string, error) { // generate a private key, with recovery phrase - info, secret, err := keyring.NewInMemory().NewMnemonic("name", keyring.English, types.FullFundraiserPath, algo.AltSecp256k1) + info, secret, err := keyring.NewInMemory().NewMnemonic("name", keyring.English, types.FullFundraiserPath, algo.Secp256k1) if err != nil { return sdk.AccAddress([]byte{}), "", err } @@ -34,7 +34,7 @@ func GenerateSaveCoinKey(keybase keyring.Keyring, keyName, keyPass string, overw } // generate a private key, with recovery phrase - info, secret, err := keybase.NewMnemonic(keyName, keyring.English, types.FullFundraiserPath, algo.AltSecp256k1) + info, secret, err := keybase.NewMnemonic(keyName, keyring.English, types.FullFundraiserPath, algo.Secp256k1) if err != nil { return sdk.AccAddress([]byte{}), "", err } diff --git a/server/init_test.go b/server/init_test.go index a45cd6b240c..a165635734f 100644 --- a/server/init_test.go +++ b/server/init_test.go @@ -19,7 +19,7 @@ func TestGenerateCoinKey(t *testing.T) { require.NoError(t, err) // Test creation - info, err := keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), algo.AltSecp256k1) + info, err := keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), algo.Secp256k1) require.NoError(t, err) require.Equal(t, addr, info.GetAddress()) } @@ -41,7 +41,7 @@ func TestGenerateSaveCoinKey(t *testing.T) { require.Equal(t, addr, info.GetAddress()) // Test in-memory recovery - info, err = keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), algo.AltSecp256k1) + info, err = keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), algo.Secp256k1) require.NoError(t, err) require.Equal(t, addr, info.GetAddress()) } From c044b6fcb1699f3b104ad727cb4726b35874498f Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Fri, 3 Apr 2020 23:36:12 +0200 Subject: [PATCH 121/148] add types --- crypto/algo/algo.go | 15 --------------- crypto/algo/types.go | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 15 deletions(-) create mode 100644 crypto/algo/types.go diff --git a/crypto/algo/algo.go b/crypto/algo/algo.go index b390164a98c..bac9168182f 100644 --- a/crypto/algo/algo.go +++ b/crypto/algo/algo.go @@ -8,21 +8,6 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/hd" ) -// PubKeyType defines an algorithm to derive key-pairs which can be used for cryptographic signing. -type PubKeyType string - -const ( - // MultiType implies that a pubkey is a multisignature - MultiType = PubKeyType("multi") - // Secp256k1Type uses the Bitcoin secp256k1 ECDSA parameters. - Secp256k1Type = PubKeyType("secp256k1") - // Ed25519Type represents the Ed25519Type signature system. - // It is currently not supported for end-user keys (wallets/ledgers). - Ed25519Type = PubKeyType("ed25519") - // Sr25519Type represents the Sr25519Type signature system. - Sr25519Type = PubKeyType("sr25519") -) - var ( // Secp256k1 uses the Bitcoin secp256k1 ECDSA parameters. Secp256k1 = secp256k1Algo{} diff --git a/crypto/algo/types.go b/crypto/algo/types.go new file mode 100644 index 00000000000..3d47c5d68b3 --- /dev/null +++ b/crypto/algo/types.go @@ -0,0 +1,16 @@ +package algo + +// PubKeyType defines an algorithm to derive key-pairs which can be used for cryptographic signing. +type PubKeyType string + +const ( + // MultiType implies that a pubkey is a multisignature + MultiType = PubKeyType("multi") + // Secp256k1Type uses the Bitcoin secp256k1 ECDSA parameters. + Secp256k1Type = PubKeyType("secp256k1") + // Ed25519Type represents the Ed25519Type signature system. + // It is currently not supported for end-user keys (wallets/ledgers). + Ed25519Type = PubKeyType("ed25519") + // Sr25519Type represents the Sr25519Type signature system. + Sr25519Type = PubKeyType("sr25519") +) From 82d91a5a0c8ee90a6230936f2d81c99e7eb8580f Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Sat, 4 Apr 2020 00:18:34 +0200 Subject: [PATCH 122/148] renama package --- client/keys/add.go | 2 +- client/keys/delete_test.go | 6 +- client/keys/export_test.go | 4 +- client/keys/list_test.go | 4 +- client/keys/show_test.go | 6 +- crypto/armor_test.go | 2 +- crypto/keyring/info.go | 42 +++++------ crypto/keyring/keyring.go | 2 +- crypto/keyring/keyring_test.go | 90 +++++++++++------------ crypto/keyring/signing_algorithms.go | 12 +-- crypto/keyring/signing_algorithms_test.go | 27 +++---- crypto/keyring/types.go | 6 +- crypto/keyring/types_test.go | 4 +- crypto/{algo => privkey}/algo.go | 6 +- crypto/{algo => privkey}/types.go | 2 +- crypto/privkey/types_test.go | 14 ++++ server/init.go | 6 +- server/init_test.go | 6 +- 18 files changed, 124 insertions(+), 117 deletions(-) rename crypto/{algo => privkey}/algo.go (92%) rename crypto/{algo => privkey}/types.go (97%) create mode 100644 crypto/privkey/types_test.go diff --git a/client/keys/add.go b/client/keys/add.go index c3b2eb21b1f..0951ac0f873 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -5,7 +5,7 @@ import ( "bytes" "errors" "fmt" - algo2 "github.com/cosmos/cosmos-sdk/crypto/algo" + algo2 "github.com/cosmos/cosmos-sdk/crypto/privkey" "io" "sort" diff --git a/client/keys/delete_test.go b/client/keys/delete_test.go index 8eaf59fbdd7..b5512e5b3fe 100644 --- a/client/keys/delete_test.go +++ b/client/keys/delete_test.go @@ -1,7 +1,7 @@ package keys import ( - "github.com/cosmos/cosmos-sdk/crypto/algo" + "github.com/cosmos/cosmos-sdk/crypto/privkey" "testing" "github.com/spf13/viper" @@ -35,9 +35,9 @@ func Test_runDeleteCmd(t *testing.T) { backend := viper.GetString(flags.FlagKeyringBackend) kb, err := keyring.New(sdk.KeyringServiceName(), backend, kbHome, mockIn) require.NoError(t, err) - _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, algo.Secp256k1) + _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, privkey.Secp256k1) require.NoError(t, err) - _, _, err = kb.NewMnemonic(fakeKeyName2, keyring.English, sdk.FullFundraiserPath, algo.Secp256k1) + _, _, err = kb.NewMnemonic(fakeKeyName2, keyring.English, sdk.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) err = runDeleteCmd(deleteKeyCommand, []string{"blah"}) diff --git a/client/keys/export_test.go b/client/keys/export_test.go index 7eafaaaf5a1..002ccbaf51f 100644 --- a/client/keys/export_test.go +++ b/client/keys/export_test.go @@ -1,7 +1,7 @@ package keys import ( - "github.com/cosmos/cosmos-sdk/crypto/algo" + "github.com/cosmos/cosmos-sdk/crypto/privkey" "testing" "github.com/spf13/viper" @@ -30,7 +30,7 @@ func Test_runExportCmd(t *testing.T) { }) path := sdk.GetConfig().GetFullFundraiserPath() - _, err = kb.NewAccount("keyname1", tests.TestMnemonic, "", path, algo.Secp256k1) + _, err = kb.NewAccount("keyname1", tests.TestMnemonic, "", path, privkey.Secp256k1) require.NoError(t, err) // Now enter password diff --git a/client/keys/list_test.go b/client/keys/list_test.go index 529748dc068..33e20521ff3 100644 --- a/client/keys/list_test.go +++ b/client/keys/list_test.go @@ -1,7 +1,7 @@ package keys import ( - "github.com/cosmos/cosmos-sdk/crypto/algo" + "github.com/cosmos/cosmos-sdk/crypto/privkey" "testing" "github.com/spf13/cobra" @@ -36,7 +36,7 @@ func Test_runListCmd(t *testing.T) { require.NoError(t, err) path := "" //sdk.GetConfig().GetFullFundraiserPath() - _, err = kb.NewAccount("something", tests.TestMnemonic, "", path, algo.Secp256k1) + _, err = kb.NewAccount("something", tests.TestMnemonic, "", path, privkey.Secp256k1) require.NoError(t, err) t.Cleanup(func() { diff --git a/client/keys/show_test.go b/client/keys/show_test.go index 86139e2e015..6a7f6b78718 100644 --- a/client/keys/show_test.go +++ b/client/keys/show_test.go @@ -1,7 +1,7 @@ package keys import ( - "github.com/cosmos/cosmos-sdk/crypto/algo" + "github.com/cosmos/cosmos-sdk/crypto/privkey" "testing" "github.com/spf13/viper" @@ -58,10 +58,10 @@ func Test_runShowCmd(t *testing.T) { }) path := hd.NewFundraiserParams(1, sdk.CoinType, 0).String() - _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, algo.Secp256k1) + _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, privkey.Secp256k1) require.NoError(t, err) - _, err = kb.NewAccount(fakeKeyName2, tests.TestMnemonic, "", path, algo.Secp256k1) + _, err = kb.NewAccount(fakeKeyName2, tests.TestMnemonic, "", path, privkey.Secp256k1) require.NoError(t, err) // Now try single key diff --git a/crypto/armor_test.go b/crypto/armor_test.go index 315ea435d39..35cf98a1a9f 100644 --- a/crypto/armor_test.go +++ b/crypto/armor_test.go @@ -4,7 +4,7 @@ import ( "bytes" "errors" "fmt" - algo2 "github.com/cosmos/cosmos-sdk/crypto/algo" + algo2 "github.com/cosmos/cosmos-sdk/crypto/privkey" "io" "testing" diff --git a/crypto/keyring/info.go b/crypto/keyring/info.go index d2778a8eb71..beb07304ded 100644 --- a/crypto/keyring/info.go +++ b/crypto/keyring/info.go @@ -3,7 +3,7 @@ package keyring import ( "fmt" - "github.com/cosmos/cosmos-sdk/crypto/algo" + "github.com/cosmos/cosmos-sdk/crypto/privkey" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/multisig" @@ -25,7 +25,7 @@ type Info interface { // Bip44 Path GetPath() (*hd.BIP44Params, error) // Algo - GetAlgo() algo.PubKeyType + GetAlgo() privkey.PubKeyType } var ( @@ -38,13 +38,13 @@ var ( // localInfo is the public information about a locally stored key // Note: Algo must be last field in struct for backwards amino compatibility type localInfo struct { - Name string `json:"name"` - PubKey crypto.PubKey `json:"pubkey"` - PrivKeyArmor string `json:"privkey.armor"` - Algo algo.PubKeyType `json:"algo"` + Name string `json:"name"` + PubKey crypto.PubKey `json:"pubkey"` + PrivKeyArmor string `json:"privkey.armor"` + Algo privkey.PubKeyType `json:"algo"` } -func newLocalInfo(name string, pub crypto.PubKey, privArmor string, algo algo.PubKeyType) Info { +func newLocalInfo(name string, pub crypto.PubKey, privArmor string, algo privkey.PubKeyType) Info { return &localInfo{ Name: name, PubKey: pub, @@ -74,7 +74,7 @@ func (i localInfo) GetAddress() types.AccAddress { } // GetType implements Info interface -func (i localInfo) GetAlgo() algo.PubKeyType { +func (i localInfo) GetAlgo() privkey.PubKeyType { return i.Algo } @@ -86,13 +86,13 @@ func (i localInfo) GetPath() (*hd.BIP44Params, error) { // ledgerInfo is the public information about a Ledger key // Note: Algo must be last field in struct for backwards amino compatibility type ledgerInfo struct { - Name string `json:"name"` - PubKey crypto.PubKey `json:"pubkey"` - Path hd.BIP44Params `json:"path"` - Algo algo.PubKeyType `json:"algo"` + Name string `json:"name"` + PubKey crypto.PubKey `json:"pubkey"` + Path hd.BIP44Params `json:"path"` + Algo privkey.PubKeyType `json:"algo"` } -func newLedgerInfo(name string, pub crypto.PubKey, path hd.BIP44Params, algo algo.PubKeyType) Info { +func newLedgerInfo(name string, pub crypto.PubKey, path hd.BIP44Params, algo privkey.PubKeyType) Info { return &ledgerInfo{ Name: name, PubKey: pub, @@ -122,7 +122,7 @@ func (i ledgerInfo) GetAddress() types.AccAddress { } // GetPath implements Info interface -func (i ledgerInfo) GetAlgo() algo.PubKeyType { +func (i ledgerInfo) GetAlgo() privkey.PubKeyType { return i.Algo } @@ -135,12 +135,12 @@ func (i ledgerInfo) GetPath() (*hd.BIP44Params, error) { // offlineInfo is the public information about an offline key // Note: Algo must be last field in struct for backwards amino compatibility type offlineInfo struct { - Name string `json:"name"` - PubKey crypto.PubKey `json:"pubkey"` - Algo algo.PubKeyType `json:"algo"` + Name string `json:"name"` + PubKey crypto.PubKey `json:"pubkey"` + Algo privkey.PubKeyType `json:"algo"` } -func newOfflineInfo(name string, pub crypto.PubKey, algo algo.PubKeyType) Info { +func newOfflineInfo(name string, pub crypto.PubKey, algo privkey.PubKeyType) Info { return &offlineInfo{ Name: name, PubKey: pub, @@ -164,7 +164,7 @@ func (i offlineInfo) GetPubKey() crypto.PubKey { } // GetAlgo returns the signing algorithm for the key -func (i offlineInfo) GetAlgo() algo.PubKeyType { +func (i offlineInfo) GetAlgo() privkey.PubKeyType { return i.Algo } @@ -230,8 +230,8 @@ func (i multiInfo) GetAddress() types.AccAddress { } // GetPath implements Info interface -func (i multiInfo) GetAlgo() algo.PubKeyType { - return algo.MultiType +func (i multiInfo) GetAlgo() privkey.PubKeyType { + return privkey.MultiType } // GetPath implements Info interface diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 61fddff63a8..d691763ce7d 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -20,7 +20,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/input" "github.com/cosmos/cosmos-sdk/crypto" - salgo "github.com/cosmos/cosmos-sdk/crypto/algo" + salgo "github.com/cosmos/cosmos-sdk/crypto/privkey" "github.com/cosmos/cosmos-sdk/crypto/keys/hd" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index bb2c934b068..96fbbe30c24 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -14,8 +14,8 @@ import ( "github.com/tendermint/tendermint/crypto/secp256k1" "github.com/cosmos/cosmos-sdk/crypto" - "github.com/cosmos/cosmos-sdk/crypto/algo" - salgo "github.com/cosmos/cosmos-sdk/crypto/algo" + "github.com/cosmos/cosmos-sdk/crypto/privkey" + salgo "github.com/cosmos/cosmos-sdk/crypto/privkey" "github.com/cosmos/cosmos-sdk/crypto/keys/hd" "github.com/cosmos/cosmos-sdk/tests" "github.com/cosmos/cosmos-sdk/types" @@ -45,7 +45,7 @@ func TestNewKeyring(t *testing.T) { require.Equal(t, "unknown keyring backend fuzzy", err.Error()) mockIn.Reset("password\npassword\n") - info, _, err := kr.NewMnemonic("foo", English, types.FullFundraiserPath, algo.Secp256k1) + info, _, err := kr.NewMnemonic("foo", English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) require.Equal(t, "foo", info.GetName()) } @@ -140,7 +140,7 @@ func TestSignVerifyKeyRingWithLedger(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - i1, err := kb.SaveLedgerKey("key", algo.Secp256k1, "cosmos", 118, 0, 0) + i1, err := kb.SaveLedgerKey("key", privkey.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") @@ -161,7 +161,7 @@ func TestSignVerifyKeyRingWithLedger(t *testing.T) { require.True(t, i1.GetPubKey().VerifyBytes(d1, s1)) require.True(t, bytes.Equal(s1, s2)) - localInfo, _, err := kb.NewMnemonic("test", English, types.FullFundraiserPath, algo.Secp256k1) + localInfo, _, err := kb.NewMnemonic("test", English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) _, _, err = SignWithLedger(localInfo, d1) require.Error(t, err) @@ -174,7 +174,7 @@ func TestSignVerifyKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - algo := algo.Secp256k1 + algo := privkey.Secp256k1 n1, n2, n3 := "some dude", "a dudette", "dude-ish" @@ -253,7 +253,7 @@ func TestExportImportKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, algo.Secp256k1) + info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) require.Equal(t, info.GetName(), "john") @@ -286,7 +286,7 @@ func TestExportImportPubKeyKeyRing(t *testing.T) { t.Cleanup(cleanup) kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - algo := algo.Secp256k1 + algo := privkey.Secp256k1 // CreateMnemonic a private-public key pair and ensure consistency info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, algo) @@ -328,7 +328,7 @@ func TestAdvancedKeyManagementKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - algo := algo.Secp256k1 + algo := privkey.Secp256k1 n1, n2 := "old-name", "new name" // make sure key works with initial password @@ -363,7 +363,7 @@ func TestSeedPhraseKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - algo := algo.Secp256k1 + algo := privkey.Secp256k1 n1, n2 := "lost-key", "found-again" // make sure key works with initial password @@ -394,7 +394,7 @@ func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - _, _, err = kb.NewMnemonic("john", English, types.FullFundraiserPath, algo.Secp256k1) + _, _, err = kb.NewMnemonic("john", English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) keystr, err := kb.ExportPrivKeyArmor("john", "somepassword") @@ -421,7 +421,7 @@ func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { func TestInMemoryLanguage(t *testing.T) { kb := NewInMemory() - _, _, err := kb.NewMnemonic("something", Japanese, types.FullFundraiserPath, algo.Secp256k1) + _, _, err := kb.NewMnemonic("something", Japanese, types.FullFundraiserPath, privkey.Secp256k1) require.Error(t, err) require.Equal(t, "unsupported language: only english is supported", err.Error()) } @@ -442,7 +442,7 @@ func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { _, err := kb.NewAccount( "some_account", "malarkey pair crucial catch public canyon evil outer stage ten gym tornado", - "", hd.CreateHDPath(118, 0, 0).String(), algo.Secp256k1) + "", hd.CreateHDPath(118, 0, 0).String(), privkey.Secp256k1) require.Error(t, err) require.Equal(t, "Invalid mnemonic", err.Error()) } @@ -450,7 +450,7 @@ func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { func TestInMemoryCreateLedger(t *testing.T) { kb := NewInMemory() - ledger, err := kb.SaveLedgerKey("some_account", algo.Secp256k1, "cosmos", 118, 3, 1) + ledger, err := kb.SaveLedgerKey("some_account", privkey.Secp256k1, "cosmos", 118, 3, 1) if err != nil { require.Error(t, err) @@ -487,7 +487,7 @@ func TestInMemoryKeyManagement(t *testing.T) { // make the storage with reasonable defaults cstore := NewInMemory() - algo := algo.Secp256k1 + algo := privkey.Secp256k1 n1, n2, n3 := "personal", "business", "other" // Check empty state @@ -570,7 +570,7 @@ func TestInMemoryKeyManagement(t *testing.T) { // signatures func TestInMemorySignVerify(t *testing.T) { cstore := NewInMemory() - algo := algo.Secp256k1 + algo := privkey.Secp256k1 n1, n2, n3 := "some dude", "a dudette", "dude-ish" @@ -649,7 +649,7 @@ func TestInMemoryExportImport(t *testing.T) { // make the storage with reasonable defaults cstore := NewInMemory() - info, _, err := cstore.NewMnemonic("john", English, types.FullFundraiserPath, algo.Secp256k1) + info, _, err := cstore.NewMnemonic("john", English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) require.Equal(t, info.GetName(), "john") @@ -679,7 +679,7 @@ func TestInMemoryExportImport(t *testing.T) { func TestInMemoryExportImportPrivKey(t *testing.T) { kb := NewInMemory() - info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, algo.Secp256k1) + info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) require.Equal(t, info.GetName(), "john") priv1, err := kb.Key("john") @@ -707,7 +707,7 @@ func TestInMemoryExportImportPubKey(t *testing.T) { cstore := NewInMemory() // CreateMnemonic a private-public key pair and ensure consistency - info, _, err := cstore.NewMnemonic("john", English, types.FullFundraiserPath, algo.Secp256k1) + info, _, err := cstore.NewMnemonic("john", English, types.FullFundraiserPath, privkey.Secp256k1) require.Nil(t, err) require.NotEqual(t, info, "") require.Equal(t, info.GetName(), "john") @@ -742,7 +742,7 @@ func TestInMemoryAdvancedKeyManagement(t *testing.T) { // make the storage with reasonable defaults cstore := NewInMemory() - algo := algo.Secp256k1 + algo := privkey.Secp256k1 n1, n2 := "old-name", "new name" // make sure key works with initial password @@ -777,7 +777,7 @@ func TestInMemorySeedPhrase(t *testing.T) { // make the storage with reasonable defaults cstore := NewInMemory() - algo := algo.Secp256k1 + algo := privkey.Secp256k1 n1, n2 := "lost-key", "found-again" // make sure key works with initial password @@ -810,17 +810,17 @@ func TestKeyChain_ShouldFailWhenAddingSameGeneratedAccount(t *testing.T) { require.NoError(t, err) // Given we create a mnemonic - _, seed, err := kr.NewMnemonic("test", English, "", algo.Secp256k1) + _, seed, err := kr.NewMnemonic("test", English, "", privkey.Secp256k1) require.NoError(t, err) require.NoError(t, kr.Delete("test")) path := hd.CreateHDPath(118, 0, 0).String() - _, err = kr.NewAccount("test1", seed, "", path, algo.Secp256k1) + _, err = kr.NewAccount("test1", seed, "", path, privkey.Secp256k1) require.NoError(t, err) // Creating another account with different uid but same seed should fail due to have same pub address - _, err = kr.NewAccount("test2", seed, "", path, algo.Secp256k1) + _, err = kr.NewAccount("test2", seed, "", path, privkey.Secp256k1) require.Error(t, err) } @@ -828,7 +828,7 @@ func ExampleNew() { // Select the encryption and storage for your cryptostore cstore := NewInMemory() - sec := algo.Secp256k1 + sec := privkey.Secp256k1 // Add keys and see they return in alphabetical order bob, _, err := cstore.NewMnemonic("Bob", English, types.FullFundraiserPath, sec) @@ -891,11 +891,11 @@ func TestAltKeyring_List(t *testing.T) { // Create 3 keys uid1, uid2, uid3 := "Zkey", "Bkey", "Rkey" - _, _, err = keyring.NewMnemonic(uid1, English, types.FullFundraiserPath, algo.Secp256k1) + _, _, err = keyring.NewMnemonic(uid1, English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) - _, _, err = keyring.NewMnemonic(uid2, English, types.FullFundraiserPath, algo.Secp256k1) + _, _, err = keyring.NewMnemonic(uid2, English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) - _, _, err = keyring.NewMnemonic(uid3, English, types.FullFundraiserPath, algo.Secp256k1) + _, _, err = keyring.NewMnemonic(uid3, English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) list, err = keyring.List() @@ -927,7 +927,7 @@ func TestAltKeyring_NewAccount(t *testing.T) { _, err = keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.FullFundraiserPath, notSupportedAlgo{}) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) - info, err := keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.FullFundraiserPath, algo.Secp256k1) + info, err := keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) require.Equal(t, uid, info.GetName()) @@ -948,7 +948,7 @@ func TestAltKeyring_SaveLedgerKey(t *testing.T) { _, err = keyring.SaveLedgerKey("key", notSupportedAlgo{}, "cosmos", 118, 0, 0) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) - ledger, err := keyring.SaveLedgerKey("some_account", algo.Secp256k1, "cosmos", 118, 3, 1) + ledger, err := keyring.SaveLedgerKey("some_account", privkey.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") @@ -985,7 +985,7 @@ func TestAltKeyring_Get(t *testing.T) { require.NoError(t, err) uid := someKey - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) key, err := keyring.Key(uid) @@ -1001,7 +1001,7 @@ func TestAltKeyring_KeyByAddress(t *testing.T) { require.NoError(t, err) uid := someKey - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) key, err := keyring.KeyByAddress(mnemonic.GetAddress()) @@ -1017,7 +1017,7 @@ func TestAltKeyring_Delete(t *testing.T) { require.NoError(t, err) uid := someKey - _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) list, err := keyring.List() @@ -1040,7 +1040,7 @@ func TestAltKeyring_DeleteByAddress(t *testing.T) { require.NoError(t, err) uid := someKey - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) list, err := keyring.List() @@ -1070,11 +1070,11 @@ func TestAltKeyring_SavePubKey(t *testing.T) { priv := ed25519.GenPrivKey() pub := priv.PubKey() - info, err := keyring.SavePubKey(key, pub, algo.Secp256k1.Name()) + info, err := keyring.SavePubKey(key, pub, privkey.Secp256k1.Name()) require.Nil(t, err) require.Equal(t, pub, info.GetPubKey()) require.Equal(t, key, info.GetName()) - require.Equal(t, algo.Secp256k1.Name(), info.GetAlgo()) + require.Equal(t, privkey.Secp256k1.Name(), info.GetAlgo()) list, err = keyring.List() require.NoError(t, err) @@ -1088,9 +1088,9 @@ func TestAltKeyring_SaveMultisig(t *testing.T) { keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - mnemonic1, _, err := keyring.NewMnemonic("key1", English, types.FullFundraiserPath, algo.Secp256k1) + mnemonic1, _, err := keyring.NewMnemonic("key1", English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) - mnemonic2, _, err := keyring.NewMnemonic("key2", English, types.FullFundraiserPath, algo.Secp256k1) + mnemonic2, _, err := keyring.NewMnemonic("key2", English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) key := "multi" @@ -1114,7 +1114,7 @@ func TestAltKeyring_Sign(t *testing.T) { require.NoError(t, err) uid := "jack" - _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) msg := []byte("some message") @@ -1133,7 +1133,7 @@ func TestAltKeyring_SignByAddress(t *testing.T) { require.NoError(t, err) uid := "jack" - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) msg := []byte("some message") @@ -1152,7 +1152,7 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { require.NoError(t, err) uid := theID - _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) passphrase := "somePass" @@ -1181,7 +1181,7 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { require.NoError(t, err) uid := theID - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) passphrase := "somePass" @@ -1212,7 +1212,7 @@ func TestAltKeyring_ImportExportPubKey(t *testing.T) { require.NoError(t, err) uid := theID - _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) armor, err := keyring.ExportPubKeyArmor(uid) @@ -1237,7 +1237,7 @@ func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { require.NoError(t, err) uid := theID - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, algo.Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) armor, err := keyring.ExportPubKeyArmorByAddress(mnemonic.GetAddress()) @@ -1266,7 +1266,7 @@ func TestAltKeyring_ConstructorSupportedAlgos(t *testing.T) { require.EqualError(t, err, "unsupported signing algo") // but works with default signing algo. - _, _, err = keyring.NewMnemonic("test", English, types.FullFundraiserPath, algo.Secp256k1) + _, _, err = keyring.NewMnemonic("test", English, types.FullFundraiserPath, privkey.Secp256k1) require.NoError(t, err) // but we can create a new keybase with our provided algos. diff --git a/crypto/keyring/signing_algorithms.go b/crypto/keyring/signing_algorithms.go index 5a17384044e..5b114b3c732 100644 --- a/crypto/keyring/signing_algorithms.go +++ b/crypto/keyring/signing_algorithms.go @@ -3,21 +3,21 @@ package keyring import ( "fmt" - "github.com/cosmos/cosmos-sdk/crypto/algo" + "github.com/cosmos/cosmos-sdk/crypto/privkey" ) type SignatureAlgo interface { - Name() algo.PubKeyType - DeriveKey() algo.DeriveKeyFn - PrivKeyGen() algo.PrivKeyGenFn + Name() privkey.PubKeyType + DeriveKey() privkey.DeriveKeyFn + PrivKeyGen() privkey.GenerateFn } func NewSigningAlgoFromString(str string) (SignatureAlgo, error) { - if str != string(algo.Secp256k1.Name()) { + if str != string(privkey.Secp256k1.Name()) { return nil, fmt.Errorf("provided algorithm `%s` is not supported", str) } - return algo.Secp256k1, nil + return privkey.Secp256k1, nil } type SigningAlgoList []SignatureAlgo diff --git a/crypto/keyring/signing_algorithms_test.go b/crypto/keyring/signing_algorithms_test.go index 0acd18b8034..3d4ee255ad9 100644 --- a/crypto/keyring/signing_algorithms_test.go +++ b/crypto/keyring/signing_algorithms_test.go @@ -4,20 +4,13 @@ import ( "fmt" "testing" - "github.com/cosmos/cosmos-sdk/crypto/algo" + "github.com/cosmos/cosmos-sdk/crypto/privkey" "github.com/stretchr/testify/require" "github.com/stretchr/testify/assert" ) -func TestDefaults(t *testing.T) { - require.Equal(t, algo.PubKeyType("multi"), algo.MultiType) - require.Equal(t, algo.PubKeyType("secp256k1"), algo.Secp256k1Type) - require.Equal(t, algo.PubKeyType("ed25519"), algo.Ed25519Type) - require.Equal(t, algo.PubKeyType("sr25519"), algo.Sr25519Type) -} - func TestNewSigningAlgoByString(t *testing.T) { tests := []struct { name string @@ -30,7 +23,7 @@ func TestNewSigningAlgoByString(t *testing.T) { "supported algorithm", "secp256k1", true, - algo.Secp256k1, + privkey.Secp256k1, nil, }, { @@ -46,7 +39,7 @@ func TestNewSigningAlgoByString(t *testing.T) { t.Run(tt.name, func(t *testing.T) { algorithm, err := NewSigningAlgoFromString(tt.algoStr) if tt.isSupported { - require.Equal(t, algo.Secp256k1, algorithm) + require.Equal(t, privkey.Secp256k1, algorithm) } else { require.EqualError(t, err, tt.expectedErr.Error()) } @@ -56,24 +49,24 @@ func TestNewSigningAlgoByString(t *testing.T) { func TestAltSigningAlgoList_Contains(t *testing.T) { list := SigningAlgoList{ - algo.Secp256k1, + privkey.Secp256k1, } - assert.True(t, list.Contains(algo.Secp256k1)) + assert.True(t, list.Contains(privkey.Secp256k1)) assert.False(t, list.Contains(notSupportedAlgo{})) } type notSupportedAlgo struct { } -func (n notSupportedAlgo) Name() algo.PubKeyType { +func (n notSupportedAlgo) Name() privkey.PubKeyType { return "notSupported" } -func (n notSupportedAlgo) DeriveKey() algo.DeriveKeyFn { - return algo.Secp256k1DeriveKey +func (n notSupportedAlgo) DeriveKey() privkey.DeriveKeyFn { + return privkey.Secp256k1DeriveKey } -func (n notSupportedAlgo) PrivKeyGen() algo.PrivKeyGenFn { - return algo.Secp256k1PrivKeyGen +func (n notSupportedAlgo) PrivKeyGen() privkey.GenerateFn { + return privkey.Secp256k1PrivKeyGen } diff --git a/crypto/keyring/types.go b/crypto/keyring/types.go index d4c5bdbad47..f28d7a5d1b7 100644 --- a/crypto/keyring/types.go +++ b/crypto/keyring/types.go @@ -1,7 +1,7 @@ package keyring import ( - "github.com/cosmos/cosmos-sdk/crypto/algo" + "github.com/cosmos/cosmos-sdk/crypto/privkey" "github.com/tendermint/tendermint/crypto" ) @@ -65,7 +65,7 @@ func (kt KeyType) String() string { type ( // DeriveKeyFunc defines the function to derive a new key from a seed and hd path - DeriveKeyFunc func(mnemonic string, bip39Passphrase, hdPath string, algo algo.PubKeyType) ([]byte, error) + DeriveKeyFunc func(mnemonic string, bip39Passphrase, hdPath string, algo privkey.PubKeyType) ([]byte, error) // PrivKeyGenFunc defines the function to convert derived key bytes to a tendermint private key - PrivKeyGenFunc func(bz []byte, algo algo.PubKeyType) (crypto.PrivKey, error) + PrivKeyGenFunc func(bz []byte, algo privkey.PubKeyType) (crypto.PrivKey, error) ) diff --git a/crypto/keyring/types_test.go b/crypto/keyring/types_test.go index 61fec4437e2..6f6a4b38049 100644 --- a/crypto/keyring/types_test.go +++ b/crypto/keyring/types_test.go @@ -2,7 +2,7 @@ package keyring import ( "encoding/hex" - "github.com/cosmos/cosmos-sdk/crypto/algo" + "github.com/cosmos/cosmos-sdk/crypto/privkey" "testing" "github.com/stretchr/testify/assert" @@ -17,7 +17,7 @@ func Test_writeReadLedgerInfo(t *testing.T) { bz, _ := hex.DecodeString("035AD6810A47F073553FF30D2FCC7E0D3B1C0B74B61A1AAA2582344037151E143A") copy(tmpKey[:], bz) - lInfo := newLedgerInfo("some_name", tmpKey, *hd.NewFundraiserParams(5, sdk.CoinType, 1), algo.Secp256k1Type) + lInfo := newLedgerInfo("some_name", tmpKey, *hd.NewFundraiserParams(5, sdk.CoinType, 1), privkey.Secp256k1Type) assert.Equal(t, TypeLedger, lInfo.GetType()) path, err := lInfo.GetPath() diff --git a/crypto/algo/algo.go b/crypto/privkey/algo.go similarity index 92% rename from crypto/algo/algo.go rename to crypto/privkey/algo.go index bac9168182f..540618abb22 100644 --- a/crypto/algo/algo.go +++ b/crypto/privkey/algo.go @@ -1,4 +1,4 @@ -package algo +package privkey import ( "github.com/cosmos/go-bip39" @@ -14,7 +14,7 @@ var ( ) type DeriveKeyFn func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) -type PrivKeyGenFn func(bz []byte) crypto.PrivKey +type GenerateFn func(bz []byte) crypto.PrivKey type secp256k1Algo struct { } @@ -27,7 +27,7 @@ func (s secp256k1Algo) DeriveKey() DeriveKeyFn { return Secp256k1DeriveKey } -func (s secp256k1Algo) PrivKeyGen() PrivKeyGenFn { +func (s secp256k1Algo) PrivKeyGen() GenerateFn { return Secp256k1PrivKeyGen } diff --git a/crypto/algo/types.go b/crypto/privkey/types.go similarity index 97% rename from crypto/algo/types.go rename to crypto/privkey/types.go index 3d47c5d68b3..1569cf7aefd 100644 --- a/crypto/algo/types.go +++ b/crypto/privkey/types.go @@ -1,4 +1,4 @@ -package algo +package privkey // PubKeyType defines an algorithm to derive key-pairs which can be used for cryptographic signing. type PubKeyType string diff --git a/crypto/privkey/types_test.go b/crypto/privkey/types_test.go new file mode 100644 index 00000000000..a98167e717e --- /dev/null +++ b/crypto/privkey/types_test.go @@ -0,0 +1,14 @@ +package privkey + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestDefaults(t *testing.T) { + require.Equal(t, PubKeyType("multi"), MultiType) + require.Equal(t, PubKeyType("secp256k1"), Secp256k1Type) + require.Equal(t, PubKeyType("ed25519"), Ed25519Type) + require.Equal(t, PubKeyType("sr25519"), Sr25519Type) +} diff --git a/server/init.go b/server/init.go index 19c2ec057fe..ce679609b0f 100644 --- a/server/init.go +++ b/server/init.go @@ -2,7 +2,7 @@ package server import ( "fmt" - "github.com/cosmos/cosmos-sdk/crypto/algo" + "github.com/cosmos/cosmos-sdk/crypto/privkey" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/types" @@ -14,7 +14,7 @@ import ( // phrase to recover the private key. func GenerateCoinKey() (sdk.AccAddress, string, error) { // generate a private key, with recovery phrase - info, secret, err := keyring.NewInMemory().NewMnemonic("name", keyring.English, types.FullFundraiserPath, algo.Secp256k1) + info, secret, err := keyring.NewInMemory().NewMnemonic("name", keyring.English, types.FullFundraiserPath, privkey.Secp256k1) if err != nil { return sdk.AccAddress([]byte{}), "", err } @@ -34,7 +34,7 @@ func GenerateSaveCoinKey(keybase keyring.Keyring, keyName, keyPass string, overw } // generate a private key, with recovery phrase - info, secret, err := keybase.NewMnemonic(keyName, keyring.English, types.FullFundraiserPath, algo.Secp256k1) + info, secret, err := keybase.NewMnemonic(keyName, keyring.English, types.FullFundraiserPath, privkey.Secp256k1) if err != nil { return sdk.AccAddress([]byte{}), "", err } diff --git a/server/init_test.go b/server/init_test.go index a165635734f..2ff6e5d48fa 100644 --- a/server/init_test.go +++ b/server/init_test.go @@ -1,7 +1,7 @@ package server_test import ( - "github.com/cosmos/cosmos-sdk/crypto/algo" + "github.com/cosmos/cosmos-sdk/crypto/privkey" "testing" "github.com/stretchr/testify/require" @@ -19,7 +19,7 @@ func TestGenerateCoinKey(t *testing.T) { require.NoError(t, err) // Test creation - info, err := keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), algo.Secp256k1) + info, err := keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), privkey.Secp256k1) require.NoError(t, err) require.Equal(t, addr, info.GetAddress()) } @@ -41,7 +41,7 @@ func TestGenerateSaveCoinKey(t *testing.T) { require.Equal(t, addr, info.GetAddress()) // Test in-memory recovery - info, err = keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), algo.Secp256k1) + info, err = keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), privkey.Secp256k1) require.NoError(t, err) require.Equal(t, addr, info.GetAddress()) } From 5e49fba6522ad8746150dde2cbb1fb335cceefb2 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Sat, 4 Apr 2020 00:39:15 +0200 Subject: [PATCH 123/148] make format --- client/keys/add.go | 3 ++- client/keys/delete_test.go | 3 ++- client/keys/export_test.go | 3 ++- client/keys/list_test.go | 3 ++- client/keys/show_test.go | 3 ++- crypto/armor_test.go | 3 ++- crypto/keyring/keyring.go | 2 +- crypto/keyring/keyring_test.go | 2 +- crypto/keyring/types.go | 3 ++- crypto/keyring/types_test.go | 3 ++- server/init.go | 1 + server/init_test.go | 3 ++- x/auth/types/params_test.go | 3 ++- 13 files changed, 23 insertions(+), 12 deletions(-) diff --git a/client/keys/add.go b/client/keys/add.go index 0951ac0f873..c2ec3c8c2e3 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -5,10 +5,11 @@ import ( "bytes" "errors" "fmt" - algo2 "github.com/cosmos/cosmos-sdk/crypto/privkey" "io" "sort" + algo2 "github.com/cosmos/cosmos-sdk/crypto/privkey" + bip39 "github.com/cosmos/go-bip39" "github.com/cosmos/cosmos-sdk/client/flags" diff --git a/client/keys/delete_test.go b/client/keys/delete_test.go index b5512e5b3fe..bbc0fefac44 100644 --- a/client/keys/delete_test.go +++ b/client/keys/delete_test.go @@ -1,9 +1,10 @@ package keys import ( - "github.com/cosmos/cosmos-sdk/crypto/privkey" "testing" + "github.com/cosmos/cosmos-sdk/crypto/privkey" + "github.com/spf13/viper" "github.com/stretchr/testify/require" diff --git a/client/keys/export_test.go b/client/keys/export_test.go index 002ccbaf51f..be1809cc644 100644 --- a/client/keys/export_test.go +++ b/client/keys/export_test.go @@ -1,9 +1,10 @@ package keys import ( - "github.com/cosmos/cosmos-sdk/crypto/privkey" "testing" + "github.com/cosmos/cosmos-sdk/crypto/privkey" + "github.com/spf13/viper" "github.com/stretchr/testify/require" diff --git a/client/keys/list_test.go b/client/keys/list_test.go index 33e20521ff3..dcf38cd102d 100644 --- a/client/keys/list_test.go +++ b/client/keys/list_test.go @@ -1,9 +1,10 @@ package keys import ( - "github.com/cosmos/cosmos-sdk/crypto/privkey" "testing" + "github.com/cosmos/cosmos-sdk/crypto/privkey" + "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/stretchr/testify/require" diff --git a/client/keys/show_test.go b/client/keys/show_test.go index 6a7f6b78718..7e4d225e44e 100644 --- a/client/keys/show_test.go +++ b/client/keys/show_test.go @@ -1,9 +1,10 @@ package keys import ( - "github.com/cosmos/cosmos-sdk/crypto/privkey" "testing" + "github.com/cosmos/cosmos-sdk/crypto/privkey" + "github.com/spf13/viper" "github.com/stretchr/testify/require" diff --git a/crypto/armor_test.go b/crypto/armor_test.go index 35cf98a1a9f..aa49e22cf45 100644 --- a/crypto/armor_test.go +++ b/crypto/armor_test.go @@ -4,10 +4,11 @@ import ( "bytes" "errors" "fmt" - algo2 "github.com/cosmos/cosmos-sdk/crypto/privkey" "io" "testing" + algo2 "github.com/cosmos/cosmos-sdk/crypto/privkey" + "github.com/stretchr/testify/require" "github.com/tendermint/crypto/bcrypt" tmcrypto "github.com/tendermint/tendermint/crypto" diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index d691763ce7d..6b47f45edab 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -20,8 +20,8 @@ import ( "github.com/cosmos/cosmos-sdk/client/input" "github.com/cosmos/cosmos-sdk/crypto" - salgo "github.com/cosmos/cosmos-sdk/crypto/privkey" "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + salgo "github.com/cosmos/cosmos-sdk/crypto/privkey" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 96fbbe30c24..9edca768be9 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -14,9 +14,9 @@ import ( "github.com/tendermint/tendermint/crypto/secp256k1" "github.com/cosmos/cosmos-sdk/crypto" + "github.com/cosmos/cosmos-sdk/crypto/keys/hd" "github.com/cosmos/cosmos-sdk/crypto/privkey" salgo "github.com/cosmos/cosmos-sdk/crypto/privkey" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" "github.com/cosmos/cosmos-sdk/tests" "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types" diff --git a/crypto/keyring/types.go b/crypto/keyring/types.go index f28d7a5d1b7..634c8e1a889 100644 --- a/crypto/keyring/types.go +++ b/crypto/keyring/types.go @@ -1,8 +1,9 @@ package keyring import ( - "github.com/cosmos/cosmos-sdk/crypto/privkey" "github.com/tendermint/tendermint/crypto" + + "github.com/cosmos/cosmos-sdk/crypto/privkey" ) // Language is a language to create the BIP 39 mnemonic in. diff --git a/crypto/keyring/types_test.go b/crypto/keyring/types_test.go index 6f6a4b38049..74374c703b6 100644 --- a/crypto/keyring/types_test.go +++ b/crypto/keyring/types_test.go @@ -2,9 +2,10 @@ package keyring import ( "encoding/hex" - "github.com/cosmos/cosmos-sdk/crypto/privkey" "testing" + "github.com/cosmos/cosmos-sdk/crypto/privkey" + "github.com/stretchr/testify/assert" "github.com/tendermint/tendermint/crypto/secp256k1" diff --git a/server/init.go b/server/init.go index ce679609b0f..4cec406f151 100644 --- a/server/init.go +++ b/server/init.go @@ -2,6 +2,7 @@ package server import ( "fmt" + "github.com/cosmos/cosmos-sdk/crypto/privkey" "github.com/cosmos/cosmos-sdk/crypto/keyring" diff --git a/server/init_test.go b/server/init_test.go index 2ff6e5d48fa..59c3615edc5 100644 --- a/server/init_test.go +++ b/server/init_test.go @@ -1,9 +1,10 @@ package server_test import ( - "github.com/cosmos/cosmos-sdk/crypto/privkey" "testing" + "github.com/cosmos/cosmos-sdk/crypto/privkey" + "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/crypto/keyring" diff --git a/x/auth/types/params_test.go b/x/auth/types/params_test.go index f25a4491495..fcec36cb833 100644 --- a/x/auth/types/params_test.go +++ b/x/auth/types/params_test.go @@ -4,8 +4,9 @@ import ( "fmt" "testing" - "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/x/auth/types" ) func TestParamsEqual(t *testing.T) { From 3fd18c1f305f4e6f65b068abbba91debc3bd6379 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Sat, 4 Apr 2020 00:50:16 +0200 Subject: [PATCH 124/148] refactor some naming --- crypto/keyring/keyring.go | 4 +- crypto/keyring/signing_algorithms.go | 4 +- crypto/keyring/signing_algorithms_test.go | 13 +++---- crypto/privkey/algo.go | 46 +++++++++++------------ 4 files changed, 31 insertions(+), 36 deletions(-) diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 6b47f45edab..77d4872be12 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -477,12 +477,12 @@ func (ks keystore) NewAccount(uid string, mnemonic string, bip39Passphrase strin } // create master key and derive first key for keyring - derivedPriv, err := algo.DeriveKey()(mnemonic, bip39Passphrase, hdPath) + derivedPriv, err := algo.Derive()(mnemonic, bip39Passphrase, hdPath) if err != nil { return nil, err } - privKey := algo.PrivKeyGen()(derivedPriv) + privKey := algo.Generate()(derivedPriv) return ks.writeLocalKey(uid, privKey, algo.Name()) } diff --git a/crypto/keyring/signing_algorithms.go b/crypto/keyring/signing_algorithms.go index 5b114b3c732..88483b2fdf5 100644 --- a/crypto/keyring/signing_algorithms.go +++ b/crypto/keyring/signing_algorithms.go @@ -8,8 +8,8 @@ import ( type SignatureAlgo interface { Name() privkey.PubKeyType - DeriveKey() privkey.DeriveKeyFn - PrivKeyGen() privkey.GenerateFn + Derive() privkey.DeriveKeyFn + Generate() privkey.GenerateFn } func NewSigningAlgoFromString(str string) (SignatureAlgo, error) { diff --git a/crypto/keyring/signing_algorithms_test.go b/crypto/keyring/signing_algorithms_test.go index 3d4ee255ad9..0f7c1d2eeae 100644 --- a/crypto/keyring/signing_algorithms_test.go +++ b/crypto/keyring/signing_algorithms_test.go @@ -4,11 +4,10 @@ import ( "fmt" "testing" - "github.com/cosmos/cosmos-sdk/crypto/privkey" - + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/stretchr/testify/assert" + "github.com/cosmos/cosmos-sdk/crypto/privkey" ) func TestNewSigningAlgoByString(t *testing.T) { @@ -63,10 +62,10 @@ func (n notSupportedAlgo) Name() privkey.PubKeyType { return "notSupported" } -func (n notSupportedAlgo) DeriveKey() privkey.DeriveKeyFn { - return privkey.Secp256k1DeriveKey +func (n notSupportedAlgo) Derive() privkey.DeriveKeyFn { + return privkey.Secp256k1.Derive() } -func (n notSupportedAlgo) PrivKeyGen() privkey.GenerateFn { - return privkey.Secp256k1PrivKeyGen +func (n notSupportedAlgo) Generate() privkey.GenerateFn { + return privkey.Secp256k1.Generate() } diff --git a/crypto/privkey/algo.go b/crypto/privkey/algo.go index 540618abb22..4c85cae51bd 100644 --- a/crypto/privkey/algo.go +++ b/crypto/privkey/algo.go @@ -23,32 +23,28 @@ func (s secp256k1Algo) Name() PubKeyType { return Secp256k1Type } -func (s secp256k1Algo) DeriveKey() DeriveKeyFn { - return Secp256k1DeriveKey -} - -func (s secp256k1Algo) PrivKeyGen() GenerateFn { - return Secp256k1PrivKeyGen -} - -// Secp256k1PrivKeyGen generates a secp256k1 private key from the given bytes -func Secp256k1PrivKeyGen(bz []byte) crypto.PrivKey { - var bzArr [32]byte - copy(bzArr[:], bz) - return secp256k1.PrivKeySecp256k1(bzArr) -} - -// Secp256k1DeriveKey derives and returns the secp256k1 private key for the given seed and HD path. -func Secp256k1DeriveKey(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) { - seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase) - if err != nil { - return nil, err +// Derive derives and returns the secp256k1 private key for the given seed and HD path. +func (s secp256k1Algo) Derive() DeriveKeyFn { + return func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) { + seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase) + if err != nil { + return nil, err + } + + masterPriv, ch := hd.ComputeMastersFromSeed(seed) + if len(hdPath) == 0 { + return masterPriv[:], nil + } + derivedKey, err := hd.DerivePrivateKeyForPath(masterPriv, ch, hdPath) + return derivedKey[:], err } +} - masterPriv, ch := hd.ComputeMastersFromSeed(seed) - if len(hdPath) == 0 { - return masterPriv[:], nil +// Generate generates a secp256k1 private key from the given bytes +func (s secp256k1Algo) Generate() GenerateFn { + return func(bz []byte) crypto.PrivKey { + var bzArr [32]byte + copy(bzArr[:], bz) + return secp256k1.PrivKeySecp256k1(bzArr) } - derivedKey, err := hd.DerivePrivateKeyForPath(masterPriv, ch, hdPath) - return derivedKey[:], err } From a81c3f57f80945690c1e05d526ce8b06fce64094 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Sat, 4 Apr 2020 23:23:16 +0200 Subject: [PATCH 125/148] add test --- crypto/keys/hd/hdpath_test.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/crypto/keys/hd/hdpath_test.go b/crypto/keys/hd/hdpath_test.go index a5110e2cbde..5f76b4c7b6a 100644 --- a/crypto/keys/hd/hdpath_test.go +++ b/crypto/keys/hd/hdpath_test.go @@ -188,3 +188,26 @@ func ExampleSomeBIP32TestVecs() { // // c4c11d8c03625515905d7e89d25dfc66126fbc629ecca6db489a1a72fc4bda78 } + +func TestCreateHDPath(t *testing.T) { + type args struct { + coinType uint32 + account uint32 + index uint32 + } + tests := []struct { + name string + args args + want BIP44Params + }{ + {"44'/0'/0'/0/0", args{0, 0, 0}, BIP44Params{Purpose: 44}}, + {"44'/114'/0'/0/0", args{114, 0, 0}, BIP44Params{Purpose: 44, CoinType: 114, Account: 0, AddressIndex: 0}}, + {"44'/114'/1'/1/0", args{114, 1, 1}, BIP44Params{Purpose: 44, CoinType: 114, Account: 1, AddressIndex: 1}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt := tt + require.Equal(t, tt.want, *CreateHDPath(tt.args.coinType, tt.args.account, tt.args.index)) + }) + } +} From 0a4422d92330ed5e622a41f77b39fded83f2895a Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Sat, 4 Apr 2020 23:23:42 +0200 Subject: [PATCH 126/148] Proposed interface --- crypto/privkey/algo.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crypto/privkey/algo.go b/crypto/privkey/algo.go index 4c85cae51bd..1dc6c7d5ff2 100644 --- a/crypto/privkey/algo.go +++ b/crypto/privkey/algo.go @@ -16,6 +16,11 @@ var ( type DeriveKeyFn func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) type GenerateFn func(bz []byte) crypto.PrivKey +type HDWallet interface { + Derive(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) + Generate(bz []byte) crypto.PrivKey +} + type secp256k1Algo struct { } From f33a26d0e93e9dafe964fd8648aaf3c1c676902d Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Sun, 5 Apr 2020 01:03:23 +0200 Subject: [PATCH 127/148] Fix linter warning --- crypto/keys/hd/hdpath_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/crypto/keys/hd/hdpath_test.go b/crypto/keys/hd/hdpath_test.go index 5f76b4c7b6a..a1b31bb50e1 100644 --- a/crypto/keys/hd/hdpath_test.go +++ b/crypto/keys/hd/hdpath_test.go @@ -205,6 +205,7 @@ func TestCreateHDPath(t *testing.T) { {"44'/114'/1'/1/0", args{114, 1, 1}, BIP44Params{Purpose: 44, CoinType: 114, Account: 1, AddressIndex: 1}}, } for _, tt := range tests { + tt := tt t.Run(tt.name, func(t *testing.T) { tt := tt require.Equal(t, tt.want, *CreateHDPath(tt.args.coinType, tt.args.account, tt.args.index)) From 4068b60a654e521b6ddf22f857e1dd5dfcda45f5 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Sun, 5 Apr 2020 01:30:11 +0200 Subject: [PATCH 128/148] Rename, tests --- client/keys/add.go | 8 +- client/keys/add_ledger_test.go | 2 +- client/keys/delete_test.go | 8 +- client/keys/export_test.go | 8 +- client/keys/import_test.go | 2 +- client/keys/list_test.go | 6 +- client/keys/migrate_test.go | 6 +- client/keys/show_test.go | 7 +- crypto/armor_test.go | 10 +- crypto/keyring/info.go | 42 ++++---- crypto/keyring/keyring.go | 19 ++-- crypto/keyring/keyring_test.go | 98 +++++++++---------- crypto/keyring/signing_algorithms.go | 12 +-- crypto/keyring/signing_algorithms_test.go | 20 ++-- crypto/keyring/types.go | 6 +- crypto/keyring/types_test.go | 4 +- crypto/{privkey => keys/hd}/algo.go | 27 +++-- .../types_test.go => keys/hd/algo_test.go} | 2 +- crypto/privkey/types.go | 16 --- server/init.go | 7 +- server/init_test.go | 6 +- 21 files changed, 151 insertions(+), 165 deletions(-) rename crypto/{privkey => keys/hd}/algo.go (55%) rename crypto/{privkey/types_test.go => keys/hd/algo_test.go} (95%) delete mode 100644 crypto/privkey/types.go diff --git a/client/keys/add.go b/client/keys/add.go index c2ec3c8c2e3..85487be661b 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -8,8 +8,6 @@ import ( "io" "sort" - algo2 "github.com/cosmos/cosmos-sdk/crypto/privkey" - bip39 "github.com/cosmos/go-bip39" "github.com/cosmos/cosmos-sdk/client/flags" @@ -81,7 +79,7 @@ the flag --nosort is set. cmd.Flags().Uint32(flagAccount, 0, "Account number for HD derivation") cmd.Flags().Uint32(flagIndex, 0, "Address index number for HD derivation") cmd.Flags().Bool(flags.FlagIndentResponse, false, "Add indent to JSON response") - cmd.Flags().String(flagKeyAlgo, string(algo2.Secp256k1Type), "Key signing algorithm to generate keys for") + cmd.Flags().String(flagKeyAlgo, string(hd.Secp256k1Type), "Key signing algorithm to generate keys for") return cmd } @@ -122,7 +120,7 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *buf algo, err := keyring.NewSigningAlgoFromString(viper.GetString(flagKeyAlgo)) if err != nil { - algo = algo2.Secp256k1 + algo = hd.Secp256k1 } if !viper.GetBool(flags.FlagDryRun) { @@ -205,7 +203,7 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *buf } bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix() - info, err := kb.SaveLedgerKey(name, algo2.Secp256k1, bech32PrefixAccAddr, coinType, account, index) + info, err := kb.SaveLedgerKey(name, hd.Secp256k1, bech32PrefixAccAddr, coinType, account, index) if err != nil { return err } diff --git a/client/keys/add_ledger_test.go b/client/keys/add_ledger_test.go index f8be693938a..dc78c778a48 100644 --- a/client/keys/add_ledger_test.go +++ b/client/keys/add_ledger_test.go @@ -53,7 +53,7 @@ func Test_runAddCmdLedgerWithCustomCoinType(t *testing.T) { require.NoError(t, runAddCmd(cmd, []string{"keyname1"})) // Now check that it has been stored properly - kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn) + kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), kbHome, mockIn) require.NoError(t, err) require.NotNil(t, kb) t.Cleanup(func() { diff --git a/client/keys/delete_test.go b/client/keys/delete_test.go index bbc0fefac44..542bd2955af 100644 --- a/client/keys/delete_test.go +++ b/client/keys/delete_test.go @@ -3,11 +3,11 @@ package keys import ( "testing" - "github.com/cosmos/cosmos-sdk/crypto/privkey" - "github.com/spf13/viper" "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/tests" @@ -36,9 +36,9 @@ func Test_runDeleteCmd(t *testing.T) { backend := viper.GetString(flags.FlagKeyringBackend) kb, err := keyring.New(sdk.KeyringServiceName(), backend, kbHome, mockIn) require.NoError(t, err) - _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, privkey.Secp256k1) + _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, hd.Secp256k1) require.NoError(t, err) - _, _, err = kb.NewMnemonic(fakeKeyName2, keyring.English, sdk.FullFundraiserPath, privkey.Secp256k1) + _, _, err = kb.NewMnemonic(fakeKeyName2, keyring.English, sdk.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) err = runDeleteCmd(deleteKeyCommand, []string{"blah"}) diff --git a/client/keys/export_test.go b/client/keys/export_test.go index be1809cc644..8b9153a63d2 100644 --- a/client/keys/export_test.go +++ b/client/keys/export_test.go @@ -3,11 +3,11 @@ package keys import ( "testing" - "github.com/cosmos/cosmos-sdk/crypto/privkey" - "github.com/spf13/viper" "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/tests" @@ -24,14 +24,14 @@ func Test_runExportCmd(t *testing.T) { viper.Set(flags.FlagHome, kbHome) // create a key - kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn) + kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), kbHome, mockIn) require.NoError(t, err) t.Cleanup(func() { kb.Delete("keyname1") // nolint:errcheck }) path := sdk.GetConfig().GetFullFundraiserPath() - _, err = kb.NewAccount("keyname1", tests.TestMnemonic, "", path, privkey.Secp256k1) + _, err = kb.NewAccount("keyname1", tests.TestMnemonic, "", path, hd.Secp256k1) require.NoError(t, err) // Now enter password diff --git a/client/keys/import_test.go b/client/keys/import_test.go index fad892cdaa1..6451277d3e7 100644 --- a/client/keys/import_test.go +++ b/client/keys/import_test.go @@ -23,7 +23,7 @@ func Test_runImportCmd(t *testing.T) { t.Cleanup(cleanUp) viper.Set(flags.FlagHome, kbHome) - kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), mockIn) + kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), kbHome, mockIn) require.NoError(t, err) t.Cleanup(func() { kb.Delete("keyname1") // nolint:errcheck diff --git a/client/keys/list_test.go b/client/keys/list_test.go index dcf38cd102d..40e24b99e74 100644 --- a/client/keys/list_test.go +++ b/client/keys/list_test.go @@ -3,12 +3,12 @@ package keys import ( "testing" - "github.com/cosmos/cosmos-sdk/crypto/privkey" - "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/tests" @@ -37,7 +37,7 @@ func Test_runListCmd(t *testing.T) { require.NoError(t, err) path := "" //sdk.GetConfig().GetFullFundraiserPath() - _, err = kb.NewAccount("something", tests.TestMnemonic, "", path, privkey.Secp256k1) + _, err = kb.NewAccount("something", tests.TestMnemonic, "", path, hd.Secp256k1) require.NoError(t, err) t.Cleanup(func() { diff --git a/client/keys/migrate_test.go b/client/keys/migrate_test.go index aec085ecc1d..9b82b18ba16 100644 --- a/client/keys/migrate_test.go +++ b/client/keys/migrate_test.go @@ -3,6 +3,8 @@ package keys import ( "testing" + "github.com/otiai10/copy" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/tests" @@ -18,18 +20,18 @@ func Test_runMigrateCmd(t *testing.T) { mockIn, _, _ := tests.ApplyMockIO(cmd) kbHome, kbCleanUp := tests.NewTestCaseDir(t) + copy.Copy("testdata", kbHome) assert.NotNil(t, kbHome) t.Cleanup(kbCleanUp) viper.Set(flags.FlagHome, kbHome) viper.Set(cli.OutputFlag, OutputFormatText) - mockIn.Reset("test1234\ntest1234\n") assert.NoError(t, runAddCmd(cmd, []string{"keyname1"})) viper.Set(flags.FlagDryRun, true) cmd = MigrateCommand() mockIn, _, _ = tests.ApplyMockIO(cmd) - mockIn.Reset("test1234\n") + mockIn.Reset("test1234\ntest1234\n") assert.NoError(t, runMigrateCmd(cmd, []string{})) } diff --git a/client/keys/show_test.go b/client/keys/show_test.go index 7e4d225e44e..d30da4181de 100644 --- a/client/keys/show_test.go +++ b/client/keys/show_test.go @@ -3,8 +3,6 @@ package keys import ( "testing" - "github.com/cosmos/cosmos-sdk/crypto/privkey" - "github.com/spf13/viper" "github.com/stretchr/testify/require" @@ -59,10 +57,11 @@ func Test_runShowCmd(t *testing.T) { }) path := hd.NewFundraiserParams(1, sdk.CoinType, 0).String() - _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, privkey.Secp256k1) + _, err = kb.NewAccount(fakeKeyName1, tests.TestMnemonic, "", path, hd.Secp256k1) require.NoError(t, err) - _, err = kb.NewAccount(fakeKeyName2, tests.TestMnemonic, "", path, privkey.Secp256k1) + path2 := hd.NewFundraiserParams(1, sdk.CoinType, 1).String() + _, err = kb.NewAccount(fakeKeyName2, tests.TestMnemonic, "", path2, hd.Secp256k1) require.NoError(t, err) // Now try single key diff --git a/crypto/armor_test.go b/crypto/armor_test.go index aa49e22cf45..90b9c133aaf 100644 --- a/crypto/armor_test.go +++ b/crypto/armor_test.go @@ -7,8 +7,6 @@ import ( "io" "testing" - algo2 "github.com/cosmos/cosmos-sdk/crypto/privkey" - "github.com/stretchr/testify/require" "github.com/tendermint/crypto/bcrypt" tmcrypto "github.com/tendermint/tendermint/crypto" @@ -17,6 +15,8 @@ import ( "github.com/tendermint/tendermint/crypto/secp256k1" "github.com/tendermint/tendermint/crypto/xsalsa20symmetric" + "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/crypto" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/types" @@ -29,7 +29,7 @@ func TestArmorUnarmorPrivKey(t *testing.T) { require.Error(t, err) decrypted, algo, err := crypto.UnarmorDecryptPrivKey(armored, "passphrase") require.NoError(t, err) - require.Equal(t, string(algo2.Secp256k1Type), algo) + require.Equal(t, string(hd.Secp256k1Type), algo) require.True(t, priv.Equals(decrypted)) // empty string @@ -73,14 +73,14 @@ func TestArmorUnarmorPubKey(t *testing.T) { cstore := keyring.NewInMemory() // Add keys and see they return in alphabetical order - info, _, err := cstore.NewMnemonic("Bob", keyring.English, types.FullFundraiserPath, algo2.Secp256k1) + info, _, err := cstore.NewMnemonic("Bob", keyring.English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) armored := crypto.ArmorPubKeyBytes(info.GetPubKey().Bytes(), "") pubBytes, algo, err := crypto.UnarmorPubKeyBytes(armored) require.NoError(t, err) pub, err := cryptoAmino.PubKeyFromBytes(pubBytes) require.NoError(t, err) - require.Equal(t, string(algo2.Secp256k1Type), algo) + require.Equal(t, string(hd.Secp256k1Type), algo) require.True(t, pub.Equals(info.GetPubKey())) armored = crypto.ArmorPubKeyBytes(info.GetPubKey().Bytes(), "unknown") diff --git a/crypto/keyring/info.go b/crypto/keyring/info.go index beb07304ded..8cb4ff4efdf 100644 --- a/crypto/keyring/info.go +++ b/crypto/keyring/info.go @@ -3,8 +3,6 @@ package keyring import ( "fmt" - "github.com/cosmos/cosmos-sdk/crypto/privkey" - "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/multisig" @@ -25,7 +23,7 @@ type Info interface { // Bip44 Path GetPath() (*hd.BIP44Params, error) // Algo - GetAlgo() privkey.PubKeyType + GetAlgo() hd.PubKeyType } var ( @@ -38,13 +36,13 @@ var ( // localInfo is the public information about a locally stored key // Note: Algo must be last field in struct for backwards amino compatibility type localInfo struct { - Name string `json:"name"` - PubKey crypto.PubKey `json:"pubkey"` - PrivKeyArmor string `json:"privkey.armor"` - Algo privkey.PubKeyType `json:"algo"` + Name string `json:"name"` + PubKey crypto.PubKey `json:"pubkey"` + PrivKeyArmor string `json:"privkey.armor"` + Algo hd.PubKeyType `json:"algo"` } -func newLocalInfo(name string, pub crypto.PubKey, privArmor string, algo privkey.PubKeyType) Info { +func newLocalInfo(name string, pub crypto.PubKey, privArmor string, algo hd.PubKeyType) Info { return &localInfo{ Name: name, PubKey: pub, @@ -74,7 +72,7 @@ func (i localInfo) GetAddress() types.AccAddress { } // GetType implements Info interface -func (i localInfo) GetAlgo() privkey.PubKeyType { +func (i localInfo) GetAlgo() hd.PubKeyType { return i.Algo } @@ -86,13 +84,13 @@ func (i localInfo) GetPath() (*hd.BIP44Params, error) { // ledgerInfo is the public information about a Ledger key // Note: Algo must be last field in struct for backwards amino compatibility type ledgerInfo struct { - Name string `json:"name"` - PubKey crypto.PubKey `json:"pubkey"` - Path hd.BIP44Params `json:"path"` - Algo privkey.PubKeyType `json:"algo"` + Name string `json:"name"` + PubKey crypto.PubKey `json:"pubkey"` + Path hd.BIP44Params `json:"path"` + Algo hd.PubKeyType `json:"algo"` } -func newLedgerInfo(name string, pub crypto.PubKey, path hd.BIP44Params, algo privkey.PubKeyType) Info { +func newLedgerInfo(name string, pub crypto.PubKey, path hd.BIP44Params, algo hd.PubKeyType) Info { return &ledgerInfo{ Name: name, PubKey: pub, @@ -122,7 +120,7 @@ func (i ledgerInfo) GetAddress() types.AccAddress { } // GetPath implements Info interface -func (i ledgerInfo) GetAlgo() privkey.PubKeyType { +func (i ledgerInfo) GetAlgo() hd.PubKeyType { return i.Algo } @@ -135,12 +133,12 @@ func (i ledgerInfo) GetPath() (*hd.BIP44Params, error) { // offlineInfo is the public information about an offline key // Note: Algo must be last field in struct for backwards amino compatibility type offlineInfo struct { - Name string `json:"name"` - PubKey crypto.PubKey `json:"pubkey"` - Algo privkey.PubKeyType `json:"algo"` + Name string `json:"name"` + PubKey crypto.PubKey `json:"pubkey"` + Algo hd.PubKeyType `json:"algo"` } -func newOfflineInfo(name string, pub crypto.PubKey, algo privkey.PubKeyType) Info { +func newOfflineInfo(name string, pub crypto.PubKey, algo hd.PubKeyType) Info { return &offlineInfo{ Name: name, PubKey: pub, @@ -164,7 +162,7 @@ func (i offlineInfo) GetPubKey() crypto.PubKey { } // GetAlgo returns the signing algorithm for the key -func (i offlineInfo) GetAlgo() privkey.PubKeyType { +func (i offlineInfo) GetAlgo() hd.PubKeyType { return i.Algo } @@ -230,8 +228,8 @@ func (i multiInfo) GetAddress() types.AccAddress { } // GetPath implements Info interface -func (i multiInfo) GetAlgo() privkey.PubKeyType { - return privkey.MultiType +func (i multiInfo) GetAlgo() hd.PubKeyType { + return hd.MultiType } // GetPath implements Info interface diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 77d4872be12..cff8af9fc5b 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -21,7 +21,6 @@ import ( "github.com/cosmos/cosmos-sdk/client/input" "github.com/cosmos/cosmos-sdk/crypto" "github.com/cosmos/cosmos-sdk/crypto/keys/hd" - salgo "github.com/cosmos/cosmos-sdk/crypto/privkey" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) @@ -72,7 +71,7 @@ type Keyring interface { SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, coinType, account, index uint32) (Info, error) // SavePubKey stores a public key and returns the persisted Info structure. - SavePubKey(uid string, pubkey tmcrypto.PubKey, algo salgo.PubKeyType) (Info, error) + SavePubKey(uid string, pubkey tmcrypto.PubKey, algo hd.PubKeyType) (Info, error) // SaveMultisig stores and returns a new multsig (offline) key reference. SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error) @@ -158,8 +157,8 @@ type keystore struct { func newKeystore(kr keyring.Keyring, opts ...Option) keystore { // Default options for keybase options := Options{ - SupportedAlgos: SigningAlgoList{salgo.Secp256k1}, - SupportedAlgosLedger: SigningAlgoList{salgo.Secp256k1}, + SupportedAlgos: SigningAlgoList{hd.Secp256k1}, + SupportedAlgosLedger: SigningAlgoList{hd.Secp256k1}, } for _, optionFn := range opts { @@ -252,7 +251,7 @@ func (ks keystore) ImportPrivKey(uid, armor, passphrase string) error { return errors.Wrap(err, "failed to decrypt private key") } - _, err = ks.writeLocalKey(uid, privKey, salgo.PubKeyType(algo)) + _, err = ks.writeLocalKey(uid, privKey, hd.PubKeyType(algo)) if err != nil { return err } @@ -275,7 +274,7 @@ func (ks keystore) ImportPubKey(uid string, armor string) error { return err } - _, err = ks.writeOfflineKey(uid, pubKey, salgo.PubKeyType(algo)) + _, err = ks.writeOfflineKey(uid, pubKey, hd.PubKeyType(algo)) if err != nil { return err } @@ -341,7 +340,7 @@ func (ks keystore) SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, coi return ks.writeLedgerKey(uid, priv.PubKey(), *hdPath, algo.Name()) } -func (ks keystore) writeLedgerKey(name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo salgo.PubKeyType) (Info, error) { +func (ks keystore) writeLedgerKey(name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo hd.PubKeyType) (Info, error) { info := newLedgerInfo(name, pub, path, algo) err := ks.writeInfo(name, info) if err != nil { @@ -355,7 +354,7 @@ func (ks keystore) SaveMultisig(uid string, pubkey tmcrypto.PubKey) (Info, error return ks.writeMultisigKey(uid, pubkey) } -func (ks keystore) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo salgo.PubKeyType) (Info, error) { +func (ks keystore) SavePubKey(uid string, pubkey tmcrypto.PubKey, algo hd.PubKeyType) (Info, error) { return ks.writeOfflineKey(uid, pubkey, algo) } @@ -662,7 +661,7 @@ func newRealPrompt(dir string, buf io.Reader) func(string) (string, error) { } } -func (ks keystore) writeLocalKey(name string, priv tmcrypto.PrivKey, algo salgo.PubKeyType) (Info, error) { +func (ks keystore) writeLocalKey(name string, priv tmcrypto.PrivKey, algo hd.PubKeyType) (Info, error) { // encrypt private key using keyring pub := priv.PubKey() @@ -704,7 +703,7 @@ func (ks keystore) writeInfo(name string, info Info) error { return nil } -func (ks keystore) writeOfflineKey(name string, pub tmcrypto.PubKey, algo salgo.PubKeyType) (Info, error) { +func (ks keystore) writeOfflineKey(name string, pub tmcrypto.PubKey, algo hd.PubKeyType) (Info, error) { info := newOfflineInfo(name, pub, algo) err := ks.writeInfo(name, info) if err != nil { diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 9edca768be9..f07fe74b855 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -15,8 +15,6 @@ import ( "github.com/cosmos/cosmos-sdk/crypto" "github.com/cosmos/cosmos-sdk/crypto/keys/hd" - "github.com/cosmos/cosmos-sdk/crypto/privkey" - salgo "github.com/cosmos/cosmos-sdk/crypto/privkey" "github.com/cosmos/cosmos-sdk/tests" "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -45,7 +43,7 @@ func TestNewKeyring(t *testing.T) { require.Equal(t, "unknown keyring backend fuzzy", err.Error()) mockIn.Reset("password\npassword\n") - info, _, err := kr.NewMnemonic("foo", English, types.FullFundraiserPath, privkey.Secp256k1) + info, _, err := kr.NewMnemonic("foo", English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) require.Equal(t, "foo", info.GetName()) } @@ -56,7 +54,7 @@ func TestKeyManagementKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - algo := salgo.Secp256k1 + algo := hd.Secp256k1 n1, n2, n3 := "personal", "business", "other" // Check empty state @@ -113,7 +111,7 @@ func TestKeyManagementKeyRing(t *testing.T) { o1 := "offline" priv1 := ed25519.GenPrivKey() pub1 := priv1.PubKey() - i, err = kb.SavePubKey(o1, pub1, salgo.Ed25519Type) + i, err = kb.SavePubKey(o1, pub1, hd.Ed25519Type) require.Nil(t, err) require.Equal(t, pub1, i.GetPubKey()) require.Equal(t, o1, i.GetName()) @@ -140,7 +138,7 @@ func TestSignVerifyKeyRingWithLedger(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - i1, err := kb.SaveLedgerKey("key", privkey.Secp256k1, "cosmos", 118, 0, 0) + i1, 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") @@ -161,7 +159,7 @@ func TestSignVerifyKeyRingWithLedger(t *testing.T) { require.True(t, i1.GetPubKey().VerifyBytes(d1, s1)) require.True(t, bytes.Equal(s1, s2)) - localInfo, _, err := kb.NewMnemonic("test", English, types.FullFundraiserPath, privkey.Secp256k1) + localInfo, _, err := kb.NewMnemonic("test", English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) _, _, err = SignWithLedger(localInfo, d1) require.Error(t, err) @@ -174,7 +172,7 @@ func TestSignVerifyKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - algo := privkey.Secp256k1 + algo := hd.Secp256k1 n1, n2, n3 := "some dude", "a dudette", "dude-ish" @@ -253,7 +251,7 @@ func TestExportImportKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, privkey.Secp256k1) + info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) require.Equal(t, info.GetName(), "john") @@ -286,7 +284,7 @@ func TestExportImportPubKeyKeyRing(t *testing.T) { t.Cleanup(cleanup) kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - algo := privkey.Secp256k1 + algo := hd.Secp256k1 // CreateMnemonic a private-public key pair and ensure consistency info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, algo) @@ -328,7 +326,7 @@ func TestAdvancedKeyManagementKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - algo := privkey.Secp256k1 + algo := hd.Secp256k1 n1, n2 := "old-name", "new name" // make sure key works with initial password @@ -363,7 +361,7 @@ func TestSeedPhraseKeyRing(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - algo := privkey.Secp256k1 + algo := hd.Secp256k1 n1, n2 := "lost-key", "found-again" // make sure key works with initial password @@ -381,7 +379,7 @@ func TestSeedPhraseKeyRing(t *testing.T) { // let us re-create it from the mnemonic-phrase params := *hd.NewFundraiserParams(0, sdk.CoinType, 0) hdPath := params.String() - newInfo, err := kb.NewAccount(n2, mnemonic, DefaultBIP39Passphrase, hdPath, salgo.Secp256k1) + newInfo, err := kb.NewAccount(n2, mnemonic, DefaultBIP39Passphrase, hdPath, hd.Secp256k1) require.NoError(t, err) require.Equal(t, n2, newInfo.GetName()) require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) @@ -394,7 +392,7 @@ func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { kb, err := New("keybasename", "test", dir, nil) require.NoError(t, err) - _, _, err = kb.NewMnemonic("john", English, types.FullFundraiserPath, privkey.Secp256k1) + _, _, err = kb.NewMnemonic("john", English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) keystr, err := kb.ExportPrivKeyArmor("john", "somepassword") @@ -421,7 +419,7 @@ func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { func TestInMemoryLanguage(t *testing.T) { kb := NewInMemory() - _, _, err := kb.NewMnemonic("something", Japanese, types.FullFundraiserPath, privkey.Secp256k1) + _, _, err := kb.NewMnemonic("something", Japanese, types.FullFundraiserPath, hd.Secp256k1) require.Error(t, err) require.Equal(t, "unsupported language: only english is supported", err.Error()) } @@ -442,7 +440,7 @@ func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { _, err := kb.NewAccount( "some_account", "malarkey pair crucial catch public canyon evil outer stage ten gym tornado", - "", hd.CreateHDPath(118, 0, 0).String(), privkey.Secp256k1) + "", hd.CreateHDPath(118, 0, 0).String(), hd.Secp256k1) require.Error(t, err) require.Equal(t, "Invalid mnemonic", err.Error()) } @@ -450,7 +448,7 @@ func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { func TestInMemoryCreateLedger(t *testing.T) { kb := NewInMemory() - ledger, err := kb.SaveLedgerKey("some_account", privkey.Secp256k1, "cosmos", 118, 3, 1) + ledger, err := kb.SaveLedgerKey("some_account", hd.Secp256k1, "cosmos", 118, 3, 1) if err != nil { require.Error(t, err) @@ -487,7 +485,7 @@ func TestInMemoryKeyManagement(t *testing.T) { // make the storage with reasonable defaults cstore := NewInMemory() - algo := privkey.Secp256k1 + algo := hd.Secp256k1 n1, n2, n3 := "personal", "business", "other" // Check empty state @@ -544,12 +542,12 @@ func TestInMemoryKeyManagement(t *testing.T) { o1 := "offline" priv1 := ed25519.GenPrivKey() pub1 := priv1.PubKey() - i, err = cstore.SavePubKey(o1, pub1, salgo.Ed25519Type) + i, err = cstore.SavePubKey(o1, pub1, hd.Ed25519Type) require.Nil(t, err) require.Equal(t, pub1, i.GetPubKey()) require.Equal(t, o1, i.GetName()) iOffline := i.(*offlineInfo) - require.Equal(t, salgo.Ed25519Type, iOffline.GetAlgo()) + require.Equal(t, hd.Ed25519Type, iOffline.GetAlgo()) keyS, err = cstore.List() require.NoError(t, err) require.Equal(t, 2, len(keyS)) @@ -570,7 +568,7 @@ func TestInMemoryKeyManagement(t *testing.T) { // signatures func TestInMemorySignVerify(t *testing.T) { cstore := NewInMemory() - algo := privkey.Secp256k1 + algo := hd.Secp256k1 n1, n2, n3 := "some dude", "a dudette", "dude-ish" @@ -649,7 +647,7 @@ func TestInMemoryExportImport(t *testing.T) { // make the storage with reasonable defaults cstore := NewInMemory() - info, _, err := cstore.NewMnemonic("john", English, types.FullFundraiserPath, privkey.Secp256k1) + info, _, err := cstore.NewMnemonic("john", English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) require.Equal(t, info.GetName(), "john") @@ -679,7 +677,7 @@ func TestInMemoryExportImport(t *testing.T) { func TestInMemoryExportImportPrivKey(t *testing.T) { kb := NewInMemory() - info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, privkey.Secp256k1) + info, _, err := kb.NewMnemonic("john", English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) require.Equal(t, info.GetName(), "john") priv1, err := kb.Key("john") @@ -707,7 +705,7 @@ func TestInMemoryExportImportPubKey(t *testing.T) { cstore := NewInMemory() // CreateMnemonic a private-public key pair and ensure consistency - info, _, err := cstore.NewMnemonic("john", English, types.FullFundraiserPath, privkey.Secp256k1) + info, _, err := cstore.NewMnemonic("john", English, types.FullFundraiserPath, hd.Secp256k1) require.Nil(t, err) require.NotEqual(t, info, "") require.Equal(t, info.GetName(), "john") @@ -742,7 +740,7 @@ func TestInMemoryAdvancedKeyManagement(t *testing.T) { // make the storage with reasonable defaults cstore := NewInMemory() - algo := privkey.Secp256k1 + algo := hd.Secp256k1 n1, n2 := "old-name", "new name" // make sure key works with initial password @@ -777,7 +775,7 @@ func TestInMemorySeedPhrase(t *testing.T) { // make the storage with reasonable defaults cstore := NewInMemory() - algo := privkey.Secp256k1 + algo := hd.Secp256k1 n1, n2 := "lost-key", "found-again" // make sure key works with initial password @@ -810,17 +808,17 @@ func TestKeyChain_ShouldFailWhenAddingSameGeneratedAccount(t *testing.T) { require.NoError(t, err) // Given we create a mnemonic - _, seed, err := kr.NewMnemonic("test", English, "", privkey.Secp256k1) + _, seed, err := kr.NewMnemonic("test", English, "", hd.Secp256k1) require.NoError(t, err) require.NoError(t, kr.Delete("test")) path := hd.CreateHDPath(118, 0, 0).String() - _, err = kr.NewAccount("test1", seed, "", path, privkey.Secp256k1) + _, err = kr.NewAccount("test1", seed, "", path, hd.Secp256k1) require.NoError(t, err) // Creating another account with different uid but same seed should fail due to have same pub address - _, err = kr.NewAccount("test2", seed, "", path, privkey.Secp256k1) + _, err = kr.NewAccount("test2", seed, "", path, hd.Secp256k1) require.Error(t, err) } @@ -828,7 +826,7 @@ func ExampleNew() { // Select the encryption and storage for your cryptostore cstore := NewInMemory() - sec := privkey.Secp256k1 + sec := hd.Secp256k1 // Add keys and see they return in alphabetical order bob, _, err := cstore.NewMnemonic("Bob", English, types.FullFundraiserPath, sec) @@ -891,11 +889,11 @@ func TestAltKeyring_List(t *testing.T) { // Create 3 keys uid1, uid2, uid3 := "Zkey", "Bkey", "Rkey" - _, _, err = keyring.NewMnemonic(uid1, English, types.FullFundraiserPath, privkey.Secp256k1) + _, _, err = keyring.NewMnemonic(uid1, English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) - _, _, err = keyring.NewMnemonic(uid2, English, types.FullFundraiserPath, privkey.Secp256k1) + _, _, err = keyring.NewMnemonic(uid2, English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) - _, _, err = keyring.NewMnemonic(uid3, English, types.FullFundraiserPath, privkey.Secp256k1) + _, _, err = keyring.NewMnemonic(uid3, English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) list, err = keyring.List() @@ -927,7 +925,7 @@ func TestAltKeyring_NewAccount(t *testing.T) { _, err = keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.FullFundraiserPath, notSupportedAlgo{}) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) - info, err := keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.FullFundraiserPath, privkey.Secp256k1) + info, err := keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) require.Equal(t, uid, info.GetName()) @@ -948,7 +946,7 @@ func TestAltKeyring_SaveLedgerKey(t *testing.T) { _, err = keyring.SaveLedgerKey("key", notSupportedAlgo{}, "cosmos", 118, 0, 0) require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) - ledger, err := keyring.SaveLedgerKey("some_account", privkey.Secp256k1, "cosmos", 118, 3, 1) + ledger, err := keyring.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") @@ -985,7 +983,7 @@ func TestAltKeyring_Get(t *testing.T) { require.NoError(t, err) uid := someKey - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) key, err := keyring.Key(uid) @@ -1001,7 +999,7 @@ func TestAltKeyring_KeyByAddress(t *testing.T) { require.NoError(t, err) uid := someKey - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) key, err := keyring.KeyByAddress(mnemonic.GetAddress()) @@ -1017,7 +1015,7 @@ func TestAltKeyring_Delete(t *testing.T) { require.NoError(t, err) uid := someKey - _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) list, err := keyring.List() @@ -1040,7 +1038,7 @@ func TestAltKeyring_DeleteByAddress(t *testing.T) { require.NoError(t, err) uid := someKey - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) list, err := keyring.List() @@ -1070,11 +1068,11 @@ func TestAltKeyring_SavePubKey(t *testing.T) { priv := ed25519.GenPrivKey() pub := priv.PubKey() - info, err := keyring.SavePubKey(key, pub, privkey.Secp256k1.Name()) + info, err := keyring.SavePubKey(key, pub, hd.Secp256k1.Name()) require.Nil(t, err) require.Equal(t, pub, info.GetPubKey()) require.Equal(t, key, info.GetName()) - require.Equal(t, privkey.Secp256k1.Name(), info.GetAlgo()) + require.Equal(t, hd.Secp256k1.Name(), info.GetAlgo()) list, err = keyring.List() require.NoError(t, err) @@ -1088,9 +1086,9 @@ func TestAltKeyring_SaveMultisig(t *testing.T) { keyring, err := New(t.Name(), BackendTest, dir, nil) require.NoError(t, err) - mnemonic1, _, err := keyring.NewMnemonic("key1", English, types.FullFundraiserPath, privkey.Secp256k1) + mnemonic1, _, err := keyring.NewMnemonic("key1", English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) - mnemonic2, _, err := keyring.NewMnemonic("key2", English, types.FullFundraiserPath, privkey.Secp256k1) + mnemonic2, _, err := keyring.NewMnemonic("key2", English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) key := "multi" @@ -1114,7 +1112,7 @@ func TestAltKeyring_Sign(t *testing.T) { require.NoError(t, err) uid := "jack" - _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) msg := []byte("some message") @@ -1133,7 +1131,7 @@ func TestAltKeyring_SignByAddress(t *testing.T) { require.NoError(t, err) uid := "jack" - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) msg := []byte("some message") @@ -1152,7 +1150,7 @@ func TestAltKeyring_ImportExportPrivKey(t *testing.T) { require.NoError(t, err) uid := theID - _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) passphrase := "somePass" @@ -1181,7 +1179,7 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { require.NoError(t, err) uid := theID - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) passphrase := "somePass" @@ -1212,7 +1210,7 @@ func TestAltKeyring_ImportExportPubKey(t *testing.T) { require.NoError(t, err) uid := theID - _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) + _, _, err = keyring.NewMnemonic(uid, English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) armor, err := keyring.ExportPubKeyArmor(uid) @@ -1237,7 +1235,7 @@ func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { require.NoError(t, err) uid := theID - mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, privkey.Secp256k1) + mnemonic, _, err := keyring.NewMnemonic(uid, English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) armor, err := keyring.ExportPubKeyArmorByAddress(mnemonic.GetAddress()) @@ -1266,7 +1264,7 @@ func TestAltKeyring_ConstructorSupportedAlgos(t *testing.T) { require.EqualError(t, err, "unsupported signing algo") // but works with default signing algo. - _, _, err = keyring.NewMnemonic("test", English, types.FullFundraiserPath, privkey.Secp256k1) + _, _, err = keyring.NewMnemonic("test", English, types.FullFundraiserPath, hd.Secp256k1) require.NoError(t, err) // but we can create a new keybase with our provided algos. diff --git a/crypto/keyring/signing_algorithms.go b/crypto/keyring/signing_algorithms.go index 88483b2fdf5..60db71a96dc 100644 --- a/crypto/keyring/signing_algorithms.go +++ b/crypto/keyring/signing_algorithms.go @@ -3,21 +3,21 @@ package keyring import ( "fmt" - "github.com/cosmos/cosmos-sdk/crypto/privkey" + "github.com/cosmos/cosmos-sdk/crypto/keys/hd" ) type SignatureAlgo interface { - Name() privkey.PubKeyType - Derive() privkey.DeriveKeyFn - Generate() privkey.GenerateFn + Name() hd.PubKeyType + Derive() hd.DeriveFn + Generate() hd.GenerateFn } func NewSigningAlgoFromString(str string) (SignatureAlgo, error) { - if str != string(privkey.Secp256k1.Name()) { + if str != string(hd.Secp256k1.Name()) { return nil, fmt.Errorf("provided algorithm `%s` is not supported", str) } - return privkey.Secp256k1, nil + return hd.Secp256k1, nil } type SigningAlgoList []SignatureAlgo diff --git a/crypto/keyring/signing_algorithms_test.go b/crypto/keyring/signing_algorithms_test.go index 0f7c1d2eeae..559517269f0 100644 --- a/crypto/keyring/signing_algorithms_test.go +++ b/crypto/keyring/signing_algorithms_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/cosmos/cosmos-sdk/crypto/privkey" + "github.com/cosmos/cosmos-sdk/crypto/keys/hd" ) func TestNewSigningAlgoByString(t *testing.T) { @@ -22,7 +22,7 @@ func TestNewSigningAlgoByString(t *testing.T) { "supported algorithm", "secp256k1", true, - privkey.Secp256k1, + hd.Secp256k1, nil, }, { @@ -38,7 +38,7 @@ func TestNewSigningAlgoByString(t *testing.T) { t.Run(tt.name, func(t *testing.T) { algorithm, err := NewSigningAlgoFromString(tt.algoStr) if tt.isSupported { - require.Equal(t, privkey.Secp256k1, algorithm) + require.Equal(t, hd.Secp256k1, algorithm) } else { require.EqualError(t, err, tt.expectedErr.Error()) } @@ -48,24 +48,24 @@ func TestNewSigningAlgoByString(t *testing.T) { func TestAltSigningAlgoList_Contains(t *testing.T) { list := SigningAlgoList{ - privkey.Secp256k1, + hd.Secp256k1, } - assert.True(t, list.Contains(privkey.Secp256k1)) + assert.True(t, list.Contains(hd.Secp256k1)) assert.False(t, list.Contains(notSupportedAlgo{})) } type notSupportedAlgo struct { } -func (n notSupportedAlgo) Name() privkey.PubKeyType { +func (n notSupportedAlgo) Name() hd.PubKeyType { return "notSupported" } -func (n notSupportedAlgo) Derive() privkey.DeriveKeyFn { - return privkey.Secp256k1.Derive() +func (n notSupportedAlgo) Derive() hd.DeriveFn { + return hd.Secp256k1.Derive() } -func (n notSupportedAlgo) Generate() privkey.GenerateFn { - return privkey.Secp256k1.Generate() +func (n notSupportedAlgo) Generate() hd.GenerateFn { + return hd.Secp256k1.Generate() } diff --git a/crypto/keyring/types.go b/crypto/keyring/types.go index 634c8e1a889..519ab2ca71a 100644 --- a/crypto/keyring/types.go +++ b/crypto/keyring/types.go @@ -3,7 +3,7 @@ package keyring import ( "github.com/tendermint/tendermint/crypto" - "github.com/cosmos/cosmos-sdk/crypto/privkey" + "github.com/cosmos/cosmos-sdk/crypto/keys/hd" ) // Language is a language to create the BIP 39 mnemonic in. @@ -66,7 +66,7 @@ func (kt KeyType) String() string { type ( // DeriveKeyFunc defines the function to derive a new key from a seed and hd path - DeriveKeyFunc func(mnemonic string, bip39Passphrase, hdPath string, algo privkey.PubKeyType) ([]byte, error) + DeriveKeyFunc func(mnemonic string, bip39Passphrase, hdPath string, algo hd.PubKeyType) ([]byte, error) // PrivKeyGenFunc defines the function to convert derived key bytes to a tendermint private key - PrivKeyGenFunc func(bz []byte, algo privkey.PubKeyType) (crypto.PrivKey, error) + PrivKeyGenFunc func(bz []byte, algo hd.PubKeyType) (crypto.PrivKey, error) ) diff --git a/crypto/keyring/types_test.go b/crypto/keyring/types_test.go index 74374c703b6..a7de13f2d78 100644 --- a/crypto/keyring/types_test.go +++ b/crypto/keyring/types_test.go @@ -4,8 +4,6 @@ import ( "encoding/hex" "testing" - "github.com/cosmos/cosmos-sdk/crypto/privkey" - "github.com/stretchr/testify/assert" "github.com/tendermint/tendermint/crypto/secp256k1" @@ -18,7 +16,7 @@ func Test_writeReadLedgerInfo(t *testing.T) { bz, _ := hex.DecodeString("035AD6810A47F073553FF30D2FCC7E0D3B1C0B74B61A1AAA2582344037151E143A") copy(tmpKey[:], bz) - lInfo := newLedgerInfo("some_name", tmpKey, *hd.NewFundraiserParams(5, sdk.CoinType, 1), privkey.Secp256k1Type) + lInfo := newLedgerInfo("some_name", tmpKey, *hd.NewFundraiserParams(5, sdk.CoinType, 1), hd.Secp256k1Type) assert.Equal(t, TypeLedger, lInfo.GetType()) path, err := lInfo.GetPath() diff --git a/crypto/privkey/algo.go b/crypto/keys/hd/algo.go similarity index 55% rename from crypto/privkey/algo.go rename to crypto/keys/hd/algo.go index 1dc6c7d5ff2..5ee2d82c3d7 100644 --- a/crypto/privkey/algo.go +++ b/crypto/keys/hd/algo.go @@ -1,11 +1,24 @@ -package privkey +package hd import ( "github.com/cosmos/go-bip39" "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/secp256k1" +) + +// PubKeyType defines an algorithm to derive key-pairs which can be used for cryptographic signing. +type PubKeyType string - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" +const ( + // MultiType implies that a pubkey is a multisignature + MultiType = PubKeyType("multi") + // Secp256k1Type uses the Bitcoin secp256k1 ECDSA parameters. + Secp256k1Type = PubKeyType("secp256k1") + // Ed25519Type represents the Ed25519Type signature system. + // It is currently not supported for end-user keys (wallets/ledgers). + Ed25519Type = PubKeyType("ed25519") + // Sr25519Type represents the Sr25519Type signature system. + Sr25519Type = PubKeyType("sr25519") ) var ( @@ -13,10 +26,10 @@ var ( Secp256k1 = secp256k1Algo{} ) -type DeriveKeyFn func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) +type DeriveFn func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) type GenerateFn func(bz []byte) crypto.PrivKey -type HDWallet interface { +type WalletGenerator interface { Derive(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) Generate(bz []byte) crypto.PrivKey } @@ -29,18 +42,18 @@ func (s secp256k1Algo) Name() PubKeyType { } // Derive derives and returns the secp256k1 private key for the given seed and HD path. -func (s secp256k1Algo) Derive() DeriveKeyFn { +func (s secp256k1Algo) Derive() DeriveFn { return func(mnemonic string, bip39Passphrase, hdPath string) ([]byte, error) { seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase) if err != nil { return nil, err } - masterPriv, ch := hd.ComputeMastersFromSeed(seed) + masterPriv, ch := ComputeMastersFromSeed(seed) if len(hdPath) == 0 { return masterPriv[:], nil } - derivedKey, err := hd.DerivePrivateKeyForPath(masterPriv, ch, hdPath) + derivedKey, err := DerivePrivateKeyForPath(masterPriv, ch, hdPath) return derivedKey[:], err } } diff --git a/crypto/privkey/types_test.go b/crypto/keys/hd/algo_test.go similarity index 95% rename from crypto/privkey/types_test.go rename to crypto/keys/hd/algo_test.go index a98167e717e..5b5ac5d0f72 100644 --- a/crypto/privkey/types_test.go +++ b/crypto/keys/hd/algo_test.go @@ -1,4 +1,4 @@ -package privkey +package hd import ( "testing" diff --git a/crypto/privkey/types.go b/crypto/privkey/types.go deleted file mode 100644 index 1569cf7aefd..00000000000 --- a/crypto/privkey/types.go +++ /dev/null @@ -1,16 +0,0 @@ -package privkey - -// PubKeyType defines an algorithm to derive key-pairs which can be used for cryptographic signing. -type PubKeyType string - -const ( - // MultiType implies that a pubkey is a multisignature - MultiType = PubKeyType("multi") - // Secp256k1Type uses the Bitcoin secp256k1 ECDSA parameters. - Secp256k1Type = PubKeyType("secp256k1") - // Ed25519Type represents the Ed25519Type signature system. - // It is currently not supported for end-user keys (wallets/ledgers). - Ed25519Type = PubKeyType("ed25519") - // Sr25519Type represents the Sr25519Type signature system. - Sr25519Type = PubKeyType("sr25519") -) diff --git a/server/init.go b/server/init.go index 4cec406f151..c44c8acc871 100644 --- a/server/init.go +++ b/server/init.go @@ -3,9 +3,8 @@ package server import ( "fmt" - "github.com/cosmos/cosmos-sdk/crypto/privkey" - "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/crypto/keys/hd" "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -15,7 +14,7 @@ import ( // phrase to recover the private key. func GenerateCoinKey() (sdk.AccAddress, string, error) { // generate a private key, with recovery phrase - info, secret, err := keyring.NewInMemory().NewMnemonic("name", keyring.English, types.FullFundraiserPath, privkey.Secp256k1) + info, secret, err := keyring.NewInMemory().NewMnemonic("name", keyring.English, types.FullFundraiserPath, hd.Secp256k1) if err != nil { return sdk.AccAddress([]byte{}), "", err } @@ -35,7 +34,7 @@ func GenerateSaveCoinKey(keybase keyring.Keyring, keyName, keyPass string, overw } // generate a private key, with recovery phrase - info, secret, err := keybase.NewMnemonic(keyName, keyring.English, types.FullFundraiserPath, privkey.Secp256k1) + info, secret, err := keybase.NewMnemonic(keyName, keyring.English, types.FullFundraiserPath, hd.Secp256k1) if err != nil { return sdk.AccAddress([]byte{}), "", err } diff --git a/server/init_test.go b/server/init_test.go index 59c3615edc5..5706982f17c 100644 --- a/server/init_test.go +++ b/server/init_test.go @@ -3,8 +3,6 @@ package server_test import ( "testing" - "github.com/cosmos/cosmos-sdk/crypto/privkey" - "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/crypto/keyring" @@ -20,7 +18,7 @@ func TestGenerateCoinKey(t *testing.T) { require.NoError(t, err) // Test creation - info, err := keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), privkey.Secp256k1) + info, err := keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), hd.Secp256k1) require.NoError(t, err) require.Equal(t, addr, info.GetAddress()) } @@ -42,7 +40,7 @@ func TestGenerateSaveCoinKey(t *testing.T) { require.Equal(t, addr, info.GetAddress()) // Test in-memory recovery - info, err = keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), privkey.Secp256k1) + info, err = keyring.NewInMemory().NewAccount("xxx", mnemonic, "", hd.NewFundraiserParams(0, types.GetConfig().GetCoinType(), 0).String(), hd.Secp256k1) require.NoError(t, err) require.Equal(t, addr, info.GetAddress()) } From 8392cd5424c1dd549795469b285ecc656dcb70ca Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Sun, 5 Apr 2020 01:31:50 +0200 Subject: [PATCH 129/148] Rename --- client/keys/add.go | 2 +- client/keys/delete_test.go | 2 +- client/keys/export_test.go | 2 +- client/keys/list_test.go | 2 +- client/keys/show_test.go | 2 +- crypto/armor_test.go | 2 +- crypto/{keys => }/hd/algo.go | 0 crypto/{keys => }/hd/algo_test.go | 0 crypto/{keys => }/hd/fundraiser_test.go | 0 crypto/{keys => }/hd/hdpath.go | 0 crypto/{keys => }/hd/hdpath_test.go | 0 crypto/{keys => }/hd/test.json | 0 crypto/keyring/codec.go | 2 +- crypto/keyring/info.go | 2 +- crypto/keyring/keyring.go | 2 +- crypto/keyring/keyring_test.go | 2 +- crypto/keyring/signing_algorithms.go | 2 +- crypto/keyring/signing_algorithms_test.go | 2 +- crypto/keyring/types.go | 2 +- crypto/keyring/types_test.go | 2 +- crypto/ledger_mock.go | 2 +- crypto/ledger_secp256k1.go | 2 +- crypto/ledger_test.go | 2 +- server/init.go | 2 +- server/init_test.go | 2 +- 25 files changed, 19 insertions(+), 19 deletions(-) rename crypto/{keys => }/hd/algo.go (100%) rename crypto/{keys => }/hd/algo_test.go (100%) rename crypto/{keys => }/hd/fundraiser_test.go (100%) rename crypto/{keys => }/hd/hdpath.go (100%) rename crypto/{keys => }/hd/hdpath_test.go (100%) rename crypto/{keys => }/hd/test.json (100%) diff --git a/client/keys/add.go b/client/keys/add.go index 85487be661b..51c04412379 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -12,8 +12,8 @@ import ( "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/input" + "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/spf13/cobra" diff --git a/client/keys/delete_test.go b/client/keys/delete_test.go index 542bd2955af..3d2136a7252 100644 --- a/client/keys/delete_test.go +++ b/client/keys/delete_test.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/viper" "github.com/stretchr/testify/require" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/keyring" diff --git a/client/keys/export_test.go b/client/keys/export_test.go index 8b9153a63d2..99262ceaa94 100644 --- a/client/keys/export_test.go +++ b/client/keys/export_test.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/viper" "github.com/stretchr/testify/require" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/keyring" diff --git a/client/keys/list_test.go b/client/keys/list_test.go index 40e24b99e74..849ac9b8d8d 100644 --- a/client/keys/list_test.go +++ b/client/keys/list_test.go @@ -7,7 +7,7 @@ import ( "github.com/spf13/viper" "github.com/stretchr/testify/require" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/keyring" diff --git a/client/keys/show_test.go b/client/keys/show_test.go index d30da4181de..54746e0207b 100644 --- a/client/keys/show_test.go +++ b/client/keys/show_test.go @@ -11,8 +11,8 @@ import ( "github.com/tendermint/tendermint/crypto/secp256k1" "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/crypto/keys/hd" "github.com/cosmos/cosmos-sdk/tests" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/crypto/armor_test.go b/crypto/armor_test.go index 90b9c133aaf..9ebb7cc8c81 100644 --- a/crypto/armor_test.go +++ b/crypto/armor_test.go @@ -15,7 +15,7 @@ import ( "github.com/tendermint/tendermint/crypto/secp256k1" "github.com/tendermint/tendermint/crypto/xsalsa20symmetric" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto" "github.com/cosmos/cosmos-sdk/crypto/keyring" diff --git a/crypto/keys/hd/algo.go b/crypto/hd/algo.go similarity index 100% rename from crypto/keys/hd/algo.go rename to crypto/hd/algo.go diff --git a/crypto/keys/hd/algo_test.go b/crypto/hd/algo_test.go similarity index 100% rename from crypto/keys/hd/algo_test.go rename to crypto/hd/algo_test.go diff --git a/crypto/keys/hd/fundraiser_test.go b/crypto/hd/fundraiser_test.go similarity index 100% rename from crypto/keys/hd/fundraiser_test.go rename to crypto/hd/fundraiser_test.go diff --git a/crypto/keys/hd/hdpath.go b/crypto/hd/hdpath.go similarity index 100% rename from crypto/keys/hd/hdpath.go rename to crypto/hd/hdpath.go diff --git a/crypto/keys/hd/hdpath_test.go b/crypto/hd/hdpath_test.go similarity index 100% rename from crypto/keys/hd/hdpath_test.go rename to crypto/hd/hdpath_test.go diff --git a/crypto/keys/hd/test.json b/crypto/hd/test.json similarity index 100% rename from crypto/keys/hd/test.json rename to crypto/hd/test.json diff --git a/crypto/keyring/codec.go b/crypto/keyring/codec.go index a8cd37d13fe..35860e71ce4 100644 --- a/crypto/keyring/codec.go +++ b/crypto/keyring/codec.go @@ -4,7 +4,7 @@ import ( cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/crypto/hd" ) // CryptoCdc defines the codec required for keys and info diff --git a/crypto/keyring/info.go b/crypto/keyring/info.go index 8cb4ff4efdf..a391d86a943 100644 --- a/crypto/keyring/info.go +++ b/crypto/keyring/info.go @@ -6,7 +6,7 @@ import ( "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/multisig" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/types" ) diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index cff8af9fc5b..1dd6519fc49 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -20,7 +20,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/input" "github.com/cosmos/cosmos-sdk/crypto" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/crypto/hd" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index f07fe74b855..3c3112d9574 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -14,7 +14,7 @@ import ( "github.com/tendermint/tendermint/crypto/secp256k1" "github.com/cosmos/cosmos-sdk/crypto" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/tests" "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types" diff --git a/crypto/keyring/signing_algorithms.go b/crypto/keyring/signing_algorithms.go index 60db71a96dc..425f49eb859 100644 --- a/crypto/keyring/signing_algorithms.go +++ b/crypto/keyring/signing_algorithms.go @@ -3,7 +3,7 @@ package keyring import ( "fmt" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/crypto/hd" ) type SignatureAlgo interface { diff --git a/crypto/keyring/signing_algorithms_test.go b/crypto/keyring/signing_algorithms_test.go index 559517269f0..1293249b09d 100644 --- a/crypto/keyring/signing_algorithms_test.go +++ b/crypto/keyring/signing_algorithms_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/crypto/hd" ) func TestNewSigningAlgoByString(t *testing.T) { diff --git a/crypto/keyring/types.go b/crypto/keyring/types.go index 519ab2ca71a..443896d785b 100644 --- a/crypto/keyring/types.go +++ b/crypto/keyring/types.go @@ -3,7 +3,7 @@ package keyring import ( "github.com/tendermint/tendermint/crypto" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/crypto/hd" ) // Language is a language to create the BIP 39 mnemonic in. diff --git a/crypto/keyring/types_test.go b/crypto/keyring/types_test.go index a7de13f2d78..cf935d906c8 100644 --- a/crypto/keyring/types_test.go +++ b/crypto/keyring/types_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/tendermint/tendermint/crypto/secp256k1" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/crypto/hd" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/crypto/ledger_mock.go b/crypto/ledger_mock.go index 21fc8a2b0f4..20a45c158bb 100644 --- a/crypto/ledger_mock.go +++ b/crypto/ledger_mock.go @@ -14,7 +14,7 @@ import ( bip39 "github.com/cosmos/go-bip39" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/tests" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/crypto/ledger_secp256k1.go b/crypto/ledger_secp256k1.go index 2c346d4355a..809512e47d3 100644 --- a/crypto/ledger_secp256k1.go +++ b/crypto/ledger_secp256k1.go @@ -11,7 +11,7 @@ import ( tmcrypto "github.com/tendermint/tendermint/crypto" tmsecp256k1 "github.com/tendermint/tendermint/crypto/secp256k1" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/crypto/hd" ) var ( diff --git a/crypto/ledger_test.go b/crypto/ledger_test.go index fbcf9239b49..7d73a36c980 100644 --- a/crypto/ledger_test.go +++ b/crypto/ledger_test.go @@ -9,7 +9,7 @@ import ( tmcrypto "github.com/tendermint/tendermint/crypto" cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" + "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/tests" sdk "github.com/cosmos/cosmos-sdk/types" ) diff --git a/server/init.go b/server/init.go index c44c8acc871..3777af0d0ba 100644 --- a/server/init.go +++ b/server/init.go @@ -3,8 +3,8 @@ package server import ( "fmt" + "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types" diff --git a/server/init_test.go b/server/init_test.go index 5706982f17c..c2b9b469d17 100644 --- a/server/init_test.go +++ b/server/init_test.go @@ -5,8 +5,8 @@ import ( "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" "github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/tests" "github.com/cosmos/cosmos-sdk/types" From 35ab52c071ec977f8505b8b0f2ecb8eac51f1120 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Sun, 5 Apr 2020 02:04:26 +0200 Subject: [PATCH 130/148] Tidy up crypto/hd tests --- crypto/hd/algo_test.go | 12 ++--- crypto/hd/fundraiser_test.go | 16 ++++--- crypto/hd/hdpath_test.go | 71 +++++++++++++++--------------- crypto/hd/{ => testdata}/test.json | 0 4 files changed, 52 insertions(+), 47 deletions(-) rename crypto/hd/{ => testdata}/test.json (100%) diff --git a/crypto/hd/algo_test.go b/crypto/hd/algo_test.go index 5b5ac5d0f72..767b4215403 100644 --- a/crypto/hd/algo_test.go +++ b/crypto/hd/algo_test.go @@ -1,14 +1,16 @@ -package hd +package hd_test import ( "testing" "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/crypto/hd" ) func TestDefaults(t *testing.T) { - require.Equal(t, PubKeyType("multi"), MultiType) - require.Equal(t, PubKeyType("secp256k1"), Secp256k1Type) - require.Equal(t, PubKeyType("ed25519"), Ed25519Type) - require.Equal(t, PubKeyType("sr25519"), Sr25519Type) + require.Equal(t, hd.PubKeyType("multi"), hd.MultiType) + require.Equal(t, hd.PubKeyType("secp256k1"), hd.Secp256k1Type) + require.Equal(t, hd.PubKeyType("ed25519"), hd.Ed25519Type) + require.Equal(t, hd.PubKeyType("sr25519"), hd.Sr25519Type) } diff --git a/crypto/hd/fundraiser_test.go b/crypto/hd/fundraiser_test.go index 02671a869f9..0f6a539d4fd 100644 --- a/crypto/hd/fundraiser_test.go +++ b/crypto/hd/fundraiser_test.go @@ -1,4 +1,4 @@ -package hd +package hd_test import ( "encoding/hex" @@ -13,6 +13,8 @@ import ( "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/secp256k1" + + "github.com/cosmos/cosmos-sdk/crypto/hd" ) type addrData struct { @@ -25,7 +27,7 @@ type addrData struct { } func TestFullFundraiserPath(t *testing.T) { - require.Equal(t, "44'/118'/0'/0/0", NewFundraiserParams(0, 118, 0).String()) + require.Equal(t, "44'/118'/0'/0/0", hd.NewFundraiserParams(0, 118, 0).String()) } func initFundraiserTestVectors(t *testing.T) []addrData { @@ -33,14 +35,14 @@ func initFundraiserTestVectors(t *testing.T) []addrData { // var hdPath string = "m/44'/118'/0'/0/0" var hdToAddrTable []addrData - b, err := ioutil.ReadFile("test.json") + b, err := ioutil.ReadFile("testdata/test.json") if err != nil { - t.Fatalf("could not read fundraiser test vector file (test.json): %s", err) + t.Fatalf("could not read fundraiser test vector file (testdata/test.json): %s", err) } err = json.Unmarshal(b, &hdToAddrTable) if err != nil { - t.Fatalf("could not decode test vectors (test.json): %s", err) + t.Fatalf("could not decode test vectors (testdata/test.json): %s", err) } return hdToAddrTable } @@ -60,8 +62,8 @@ func TestFundraiserCompatibility(t *testing.T) { t.Log("================================") t.Logf("ROUND: %d MNEMONIC: %s", i, d.Mnemonic) - master, ch := ComputeMastersFromSeed(seed) - priv, err := DerivePrivateKeyForPath(master, ch, "44'/118'/0'/0/0") + master, ch := hd.ComputeMastersFromSeed(seed) + priv, err := hd.DerivePrivateKeyForPath(master, ch, "44'/118'/0'/0/0") require.NoError(t, err) pub := secp256k1.PrivKeySecp256k1(priv).PubKey() diff --git a/crypto/hd/hdpath_test.go b/crypto/hd/hdpath_test.go index a1b31bb50e1..9f95f7edec3 100644 --- a/crypto/hd/hdpath_test.go +++ b/crypto/hd/hdpath_test.go @@ -1,10 +1,11 @@ -package hd +package hd_test import ( "encoding/hex" "fmt" "testing" + "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/types" bip39 "github.com/cosmos/go-bip39" @@ -21,9 +22,9 @@ func mnemonicToSeed(mnemonic string) []byte { // nolint:govet func ExampleStringifyPathParams() { - path := NewParams(44, 0, 0, false, 0) + path := hd.NewParams(44, 0, 0, false, 0) fmt.Println(path.String()) - path = NewParams(44, 33, 7, true, 9) + path = hd.NewParams(44, 33, 7, true, 9) fmt.Println(path.String()) // Output: // 44'/0'/0'/0/0 @@ -31,40 +32,40 @@ func ExampleStringifyPathParams() { } func TestStringifyFundraiserPathParams(t *testing.T) { - path := NewFundraiserParams(4, types.CoinType, 22) + path := hd.NewFundraiserParams(4, types.CoinType, 22) require.Equal(t, "44'/118'/4'/0/22", path.String()) - path = NewFundraiserParams(4, types.CoinType, 57) + path = hd.NewFundraiserParams(4, types.CoinType, 57) require.Equal(t, "44'/118'/4'/0/57", path.String()) - path = NewFundraiserParams(4, 12345, 57) + path = hd.NewFundraiserParams(4, 12345, 57) require.Equal(t, "44'/12345'/4'/0/57", path.String()) } func TestPathToArray(t *testing.T) { - path := NewParams(44, 118, 1, false, 4) + path := hd.NewParams(44, 118, 1, false, 4) require.Equal(t, "[44 118 1 0 4]", fmt.Sprintf("%v", path.DerivationPath())) - path = NewParams(44, 118, 2, true, 15) + path = hd.NewParams(44, 118, 2, true, 15) require.Equal(t, "[44 118 2 1 15]", fmt.Sprintf("%v", path.DerivationPath())) } func TestParamsFromPath(t *testing.T) { goodCases := []struct { - params *BIP44Params + params *hd.BIP44Params path string }{ - {&BIP44Params{44, 0, 0, false, 0}, "44'/0'/0'/0/0"}, - {&BIP44Params{44, 1, 0, false, 0}, "44'/1'/0'/0/0"}, - {&BIP44Params{44, 0, 1, false, 0}, "44'/0'/1'/0/0"}, - {&BIP44Params{44, 0, 0, true, 0}, "44'/0'/0'/1/0"}, - {&BIP44Params{44, 0, 0, false, 1}, "44'/0'/0'/0/1"}, - {&BIP44Params{44, 1, 1, true, 1}, "44'/1'/1'/1/1"}, - {&BIP44Params{44, 118, 52, true, 41}, "44'/118'/52'/1/41"}, + {&hd.BIP44Params{44, 0, 0, false, 0}, "44'/0'/0'/0/0"}, + {&hd.BIP44Params{44, 1, 0, false, 0}, "44'/1'/0'/0/0"}, + {&hd.BIP44Params{44, 0, 1, false, 0}, "44'/0'/1'/0/0"}, + {&hd.BIP44Params{44, 0, 0, true, 0}, "44'/0'/0'/1/0"}, + {&hd.BIP44Params{44, 0, 0, false, 1}, "44'/0'/0'/0/1"}, + {&hd.BIP44Params{44, 1, 1, true, 1}, "44'/1'/1'/1/1"}, + {&hd.BIP44Params{44, 118, 52, true, 41}, "44'/118'/52'/1/41"}, } for i, c := range goodCases { - params, err := NewParamsFromPath(c.path) + params, err := hd.NewParamsFromPath(c.path) errStr := fmt.Sprintf("%d %v", i, c) assert.NoError(t, err, errStr) assert.EqualValues(t, c.params, params, errStr) @@ -93,7 +94,7 @@ func TestParamsFromPath(t *testing.T) { } for i, c := range badCases { - params, err := NewParamsFromPath(c.path) + params, err := hd.NewParamsFromPath(c.path) errStr := fmt.Sprintf("%d %v", i, c) assert.Nil(t, params, errStr) assert.Error(t, err, errStr) @@ -106,38 +107,38 @@ func ExampleSomeBIP32TestVecs() { seed := mnemonicToSeed("barrel original fuel morning among eternal " + "filter ball stove pluck matrix mechanic") - master, ch := ComputeMastersFromSeed(seed) + master, ch := hd.ComputeMastersFromSeed(seed) fmt.Println("keys from fundraiser test-vector (cosmos, bitcoin, ether)") fmt.Println() // cosmos - priv, err := DerivePrivateKeyForPath(master, ch, types.FullFundraiserPath) + priv, err := hd.DerivePrivateKeyForPath(master, ch, types.FullFundraiserPath) if err != nil { fmt.Println("INVALID") } else { fmt.Println(hex.EncodeToString(priv[:])) } // bitcoin - priv, err = DerivePrivateKeyForPath(master, ch, "44'/0'/0'/0/0") + priv, err = hd.DerivePrivateKeyForPath(master, ch, "44'/0'/0'/0/0") if err != nil { fmt.Println("INVALID") } else { fmt.Println(hex.EncodeToString(priv[:])) } // ether - priv, err = DerivePrivateKeyForPath(master, ch, "44'/60'/0'/0/0") + priv, err = hd.DerivePrivateKeyForPath(master, ch, "44'/60'/0'/0/0") if err != nil { fmt.Println("INVALID") } else { fmt.Println(hex.EncodeToString(priv[:])) } // INVALID - priv, err = DerivePrivateKeyForPath(master, ch, "X/0'/0'/0/0") + priv, err = hd.DerivePrivateKeyForPath(master, ch, "X/0'/0'/0/0") if err != nil { fmt.Println("INVALID") } else { fmt.Println(hex.EncodeToString(priv[:])) } - priv, err = DerivePrivateKeyForPath(master, ch, "-44/0'/0'/0/0") + priv, err = hd.DerivePrivateKeyForPath(master, ch, "-44/0'/0'/0/0") if err != nil { fmt.Println("INVALID") } else { @@ -151,14 +152,14 @@ func ExampleSomeBIP32TestVecs() { seed = mnemonicToSeed( "advice process birth april short trust crater change bacon monkey medal garment " + "gorilla ranch hour rival razor call lunar mention taste vacant woman sister") - master, ch = ComputeMastersFromSeed(seed) - priv, _ = DerivePrivateKeyForPath(master, ch, "44'/1'/1'/0/4") + master, ch = hd.ComputeMastersFromSeed(seed) + priv, _ = hd.DerivePrivateKeyForPath(master, ch, "44'/1'/1'/0/4") fmt.Println(hex.EncodeToString(priv[:])) seed = mnemonicToSeed("idea naive region square margin day captain habit " + "gun second farm pact pulse someone armed") - master, ch = ComputeMastersFromSeed(seed) - priv, _ = DerivePrivateKeyForPath(master, ch, "44'/0'/0'/0/420") + master, ch = hd.ComputeMastersFromSeed(seed) + priv, _ = hd.DerivePrivateKeyForPath(master, ch, "44'/0'/0'/0/420") fmt.Println(hex.EncodeToString(priv[:])) fmt.Println() @@ -167,8 +168,8 @@ func ExampleSomeBIP32TestVecs() { // bip32 path: m/0/7 seed = mnemonicToSeed("monitor flock loyal sick object grunt duty ride develop assault harsh history") - master, ch = ComputeMastersFromSeed(seed) - priv, _ = DerivePrivateKeyForPath(master, ch, "0/7") + master, ch = hd.ComputeMastersFromSeed(seed) + priv, _ = hd.DerivePrivateKeyForPath(master, ch, "0/7") fmt.Println(hex.EncodeToString(priv[:])) // Output: keys from fundraiser test-vector (cosmos, bitcoin, ether) @@ -198,17 +199,17 @@ func TestCreateHDPath(t *testing.T) { tests := []struct { name string args args - want BIP44Params + want hd.BIP44Params }{ - {"44'/0'/0'/0/0", args{0, 0, 0}, BIP44Params{Purpose: 44}}, - {"44'/114'/0'/0/0", args{114, 0, 0}, BIP44Params{Purpose: 44, CoinType: 114, Account: 0, AddressIndex: 0}}, - {"44'/114'/1'/1/0", args{114, 1, 1}, BIP44Params{Purpose: 44, CoinType: 114, Account: 1, AddressIndex: 1}}, + {"44'/0'/0'/0/0", args{0, 0, 0}, hd.BIP44Params{Purpose: 44}}, + {"44'/114'/0'/0/0", args{114, 0, 0}, hd.BIP44Params{Purpose: 44, CoinType: 114, Account: 0, AddressIndex: 0}}, + {"44'/114'/1'/1/0", args{114, 1, 1}, hd.BIP44Params{Purpose: 44, CoinType: 114, Account: 1, AddressIndex: 1}}, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { tt := tt - require.Equal(t, tt.want, *CreateHDPath(tt.args.coinType, tt.args.account, tt.args.index)) + require.Equal(t, tt.want, *hd.CreateHDPath(tt.args.coinType, tt.args.account, tt.args.index)) }) } } diff --git a/crypto/hd/test.json b/crypto/hd/testdata/test.json similarity index 100% rename from crypto/hd/test.json rename to crypto/hd/testdata/test.json From e0c825d3aa8527b38ad60f3f16c287d7f40bf186 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Sun, 5 Apr 2020 02:10:32 +0200 Subject: [PATCH 131/148] Create a doc.go --- crypto/hd/algo.go | 2 +- crypto/hd/doc.go | 12 ++++++++++++ crypto/hd/hdpath.go | 11 ----------- 3 files changed, 13 insertions(+), 12 deletions(-) create mode 100644 crypto/hd/doc.go diff --git a/crypto/hd/algo.go b/crypto/hd/algo.go index 5ee2d82c3d7..264f0ae8dfe 100644 --- a/crypto/hd/algo.go +++ b/crypto/hd/algo.go @@ -58,7 +58,7 @@ func (s secp256k1Algo) Derive() DeriveFn { } } -// Generate generates a secp256k1 private key from the given bytes +// Generate generates a secp256k1 private key from the given bytes. func (s secp256k1Algo) Generate() GenerateFn { return func(bz []byte) crypto.PrivKey { var bzArr [32]byte diff --git a/crypto/hd/doc.go b/crypto/hd/doc.go new file mode 100644 index 00000000000..38d65213c17 --- /dev/null +++ b/crypto/hd/doc.go @@ -0,0 +1,12 @@ +// Package hd provides support for hierarchical deterministic wallets generation and derivation. +// +// The user must understand the overall concept of the BIP 32 and the BIP 44 specs: +// https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki +// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki +// +// In combination with the bip39 package in go-crypto this package provides the functionality for +// deriving keys using a BIP 44 HD path, or, more general, by passing a BIP 32 path. +// +// In particular, this package (together with bip39) provides all necessary functionality to derive +// keys from mnemonics generated during the cosmos fundraiser. +package hd diff --git a/crypto/hd/hdpath.go b/crypto/hd/hdpath.go index cadb3635ae1..76326708748 100644 --- a/crypto/hd/hdpath.go +++ b/crypto/hd/hdpath.go @@ -1,14 +1,3 @@ -// Package hd provides basic functionality Hierarchical Deterministic Wallets. -// -// The user must understand the overall concept of the BIP 32 and the BIP 44 specs: -// https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki -// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki -// -// In combination with the bip39 package in go-crypto this package provides the functionality for deriving keys using a -// BIP 44 HD path, or, more general, by passing a BIP 32 path. -// -// In particular, this package (together with bip39) provides all necessary functionality to derive keys from -// mnemonics generated during the cosmos fundraiser. package hd import ( From 128d58d52c7b5bd817fafa36ae3eb9bfa5652541 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 6 Apr 2020 18:16:29 +0200 Subject: [PATCH 132/148] add better existance checking --- crypto/keyring/keyring.go | 25 +++++++++++++++++++++++-- crypto/keyring/keyring_test.go | 1 - 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 1dd6519fc49..bb387dda76b 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -679,10 +679,13 @@ func (ks keystore) writeInfo(name string, info Info) error { key := infoKey(name) serializedInfo := marshalInfo(info) - _, err := ks.db.Get(addrHexKeyAsString(info.GetAddress())) - if err != keyring.ErrKeyNotFound { + exists, err := ks.existsInDb(key, info.GetAddress()) + if exists { return fmt.Errorf("public key already exist in keybase") } + if err != nil { + return err + } err = ks.db.Set(keyring.Item{ Key: string(key), @@ -703,6 +706,24 @@ func (ks keystore) writeInfo(name string, info Info) error { return nil } +func (ks keystore) existsInDb(key []byte, address sdk.Address) (bool, error) { + _, err := ks.db.Get(addrHexKeyAsString(address)) + if err == nil { + return true, nil + } else if err != keyring.ErrKeyNotFound { + return false, err + } + + _, err = ks.db.Get(string(key)) + if err == nil { + return true, nil + } else if err != keyring.ErrKeyNotFound { + return false, err + } + + return false, nil +} + func (ks keystore) writeOfflineKey(name string, pub tmcrypto.PubKey, algo hd.PubKeyType) (Info, error) { info := newOfflineInfo(name, pub, algo) err := ks.writeInfo(name, info) diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 3c3112d9574..abfe8e4a273 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -1199,7 +1199,6 @@ func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { // Should fail importing private key on existing key. err = keyring.ImportPrivKey(newUID, armor, passphrase) require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", newUID)) - } func TestAltKeyring_ImportExportPubKey(t *testing.T) { From 5b91edafb251dd9b62508f69bf065a8c1c31bf86 Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 6 Apr 2020 18:36:33 +0200 Subject: [PATCH 133/148] refactor and fix check --- crypto/keyring/keyring.go | 20 +++++++++++--------- crypto/keyring/legacy.go | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index bb387dda76b..98b81954161 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -342,7 +342,7 @@ func (ks keystore) SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, coi func (ks keystore) writeLedgerKey(name string, pub tmcrypto.PubKey, path hd.BIP44Params, algo hd.PubKeyType) (Info, error) { info := newLedgerInfo(name, pub, path, algo) - err := ks.writeInfo(name, info) + err := ks.writeInfo(info) if err != nil { return nil, err } @@ -666,7 +666,7 @@ func (ks keystore) writeLocalKey(name string, priv tmcrypto.PrivKey, algo hd.Pub pub := priv.PubKey() info := newLocalInfo(name, pub, string(priv.Bytes()), algo) - err := ks.writeInfo(name, info) + err := ks.writeInfo(info) if err != nil { return nil, err } @@ -674,12 +674,12 @@ func (ks keystore) writeLocalKey(name string, priv tmcrypto.PrivKey, algo hd.Pub return info, nil } -func (ks keystore) writeInfo(name string, info Info) error { +func (ks keystore) writeInfo(info Info) error { // write the info by key - key := infoKey(name) + key := infoKey(info.GetName()) serializedInfo := marshalInfo(info) - exists, err := ks.existsInDb(key, info.GetAddress()) + exists, err := ks.existsInDb(info) if exists { return fmt.Errorf("public key already exist in keybase") } @@ -706,8 +706,10 @@ func (ks keystore) writeInfo(name string, info Info) error { return nil } -func (ks keystore) existsInDb(key []byte, address sdk.Address) (bool, error) { - _, err := ks.db.Get(addrHexKeyAsString(address)) +func (ks keystore) existsInDb(info Info) (bool, error) { + key := infoKey(info.GetName()) + + _, err := ks.db.Get(addrHexKeyAsString(info.GetAddress())) if err == nil { return true, nil } else if err != keyring.ErrKeyNotFound { @@ -726,7 +728,7 @@ func (ks keystore) existsInDb(key []byte, address sdk.Address) (bool, error) { func (ks keystore) writeOfflineKey(name string, pub tmcrypto.PubKey, algo hd.PubKeyType) (Info, error) { info := newOfflineInfo(name, pub, algo) - err := ks.writeInfo(name, info) + err := ks.writeInfo(info) if err != nil { return nil, err } @@ -736,7 +738,7 @@ func (ks keystore) writeOfflineKey(name string, pub tmcrypto.PubKey, algo hd.Pub func (ks keystore) writeMultisigKey(name string, pub tmcrypto.PubKey) (Info, error) { info := NewMultiInfo(name, pub) - err := ks.writeInfo(name, info) + err := ks.writeInfo(info) if err != nil { return nil, err } diff --git a/crypto/keyring/legacy.go b/crypto/keyring/legacy.go index 29766c16bc0..2aa76fdcb5f 100644 --- a/crypto/keyring/legacy.go +++ b/crypto/keyring/legacy.go @@ -222,7 +222,7 @@ func (m keyringMigrator) Import(uid string, armor string) error { return err } - return m.kr.writeInfo(uid, info) + return m.kr.writeInfo(info) } // KeybaseOption overrides options for the db. From fdc522a50fc9a3bc3b8a36b99ff12cf98ef07a57 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 6 Apr 2020 18:46:51 +0200 Subject: [PATCH 134/148] bits of refactoring --- crypto/keyring/keyring.go | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 98b81954161..1417610a013 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -707,22 +707,19 @@ func (ks keystore) writeInfo(info Info) error { } func (ks keystore) existsInDb(info Info) (bool, error) { - key := infoKey(info.GetName()) - - _, err := ks.db.Get(addrHexKeyAsString(info.GetAddress())) - if err == nil { - return true, nil + if _, err := ks.db.Get(addrHexKeyAsString(info.GetAddress())); err == nil { + return true, nil // address lookup succeeds - info exists } else if err != keyring.ErrKeyNotFound { - return false, err + return false, err // received unexpected error - returns error } - _, err = ks.db.Get(string(key)) - if err == nil { - return true, nil + if _, err := ks.db.Get(string(infoKey(info.GetName()))); err == nil { + return true, nil // uid lookup succeeds - info exists } else if err != keyring.ErrKeyNotFound { - return false, err + return false, err // received unexpected error - returns } + // both lookups failed, info does not exist return false, nil } From 4cea6bf6e92bc1efc10ba24cdaa36c660f67c321 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 6 Apr 2020 19:09:27 +0200 Subject: [PATCH 135/148] Add few more doc strings --- crypto/keyring/keyring.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 1417610a013..27fc3db78a3 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -93,7 +93,9 @@ type Signer interface { // Importer is implemented by key stores that support import of public and private keys. type Importer interface { + // ImportPrivKey imports ASCII armored passphrase-encrypted private keys. ImportPrivKey(uid, armor, passphrase string) error + // ImportPubKey imports ASCII armored public keys. ImportPubKey(uid string, armor string) error } From 2e5e287a7cc26f96979ab49b19936d08ea6ecddc Mon Sep 17 00:00:00 2001 From: Jonathan Gimeno Date: Mon, 6 Apr 2020 19:23:05 +0200 Subject: [PATCH 136/148] add checking to overwrite --- client/keys/add.go | 5 +++++ crypto/keyring/legacy_test.go | 2 +- server/init.go | 21 ++++++++++++++++----- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/client/keys/add.go b/client/keys/add.go index 51c04412379..048ea48a05a 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -134,6 +134,11 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *buf if !response { return errors.New("aborted") } + + err2 = kb.Delete(name) + if err2 != nil { + return err2 + } } multisigKeys := viper.GetStringSlice(flagMultisig) diff --git a/crypto/keyring/legacy_test.go b/crypto/keyring/legacy_test.go index 9be4a8ca6ba..11ea30bf05e 100644 --- a/crypto/keyring/legacy_test.go +++ b/crypto/keyring/legacy_test.go @@ -55,5 +55,5 @@ func TestLegacyKeybase(t *testing.T) { err = importer.Import("test", armoredInfo) require.Error(t, err) - require.Equal(t, `cannot overwrite key "test"`, err.Error()) + require.Equal(t, `public key already exist in keybase`, err.Error()) } diff --git a/server/init.go b/server/init.go index 3777af0d0ba..cf433aa1184 100644 --- a/server/init.go +++ b/server/init.go @@ -24,16 +24,27 @@ func GenerateCoinKey() (sdk.AccAddress, string, error) { // GenerateSaveCoinKey returns the address of a public key, along with the secret // phrase to recover the private key. func GenerateSaveCoinKey(keybase keyring.Keyring, keyName, keyPass string, overwrite bool) (sdk.AccAddress, string, error) { + exists := false + _, err := keybase.Key(keyName) + if err == nil { + exists = true + } + // ensure no overwrite - if !overwrite { - _, err := keybase.Key(keyName) - if err == nil { + if !overwrite && exists { + return sdk.AccAddress([]byte{}), "", fmt.Errorf( + "key already exists, overwrite is disabled") + } + + // generate a private key, with recovery phrase + if exists { + err = keybase.Delete(keyName) + if err != nil { return sdk.AccAddress([]byte{}), "", fmt.Errorf( - "key already exists, overwrite is disabled") + "failed to overwrite key") } } - // generate a private key, with recovery phrase info, secret, err := keybase.NewMnemonic(keyName, keyring.English, types.FullFundraiserPath, hd.Secp256k1) if err != nil { return sdk.AccAddress([]byte{}), "", err From acb5e7fa7a9d983e2e306b4fdd0807e72474dc45 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 6 Apr 2020 19:50:26 +0200 Subject: [PATCH 137/148] fix bugs --- client/keys/add_test.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/client/keys/add_test.go b/client/keys/add_test.go index 9ee735d9be2..5776aa8b074 100644 --- a/client/keys/add_test.go +++ b/client/keys/add_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/spf13/viper" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/libs/cli" @@ -17,14 +16,15 @@ import ( func Test_runAddCmdBasic(t *testing.T) { cmd := AddKeyCommand() - assert.NotNil(t, cmd) + require.NotNil(t, cmd) mockIn, _, _ := tests.ApplyMockIO(cmd) kbHome, kbCleanUp := tests.NewTestCaseDir(t) - assert.NotNil(t, kbHome) + require.NotNil(t, kbHome) t.Cleanup(kbCleanUp) viper.Set(flags.FlagHome, kbHome) viper.Set(cli.OutputFlag, OutputFormatText) + viper.Set(flags.FlagUseLedger, false) mockIn.Reset("y\n") kb, err := keyring.New(sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), kbHome, mockIn) @@ -33,20 +33,20 @@ func Test_runAddCmdBasic(t *testing.T) { kb.Delete("keyname1") // nolint:errcheck kb.Delete("keyname2") // nolint:errcheck }) - assert.NoError(t, runAddCmd(cmd, []string{"keyname1"})) + require.NoError(t, runAddCmd(cmd, []string{"keyname1"})) mockIn.Reset("N\n") - assert.Error(t, runAddCmd(cmd, []string{"keyname1"})) + require.Error(t, runAddCmd(cmd, []string{"keyname1"})) - assert.NoError(t, runAddCmd(cmd, []string{"keyname2"})) - assert.Error(t, runAddCmd(cmd, []string{"keyname2"})) + require.NoError(t, runAddCmd(cmd, []string{"keyname2"})) + require.Error(t, runAddCmd(cmd, []string{"keyname2"})) mockIn.Reset("y\n") - assert.NoError(t, runAddCmd(cmd, []string{"keyname2"})) + require.NoError(t, runAddCmd(cmd, []string{"keyname2"})) // test --dry-run - assert.NoError(t, runAddCmd(cmd, []string{"keyname4"})) - assert.Error(t, runAddCmd(cmd, []string{"keyname4"})) + require.NoError(t, runAddCmd(cmd, []string{"keyname4"})) + require.Error(t, runAddCmd(cmd, []string{"keyname4"})) viper.Set(flags.FlagDryRun, true) - assert.NoError(t, runAddCmd(cmd, []string{"keyname4"})) + require.NoError(t, runAddCmd(cmd, []string{"keyname4"})) } From c16d93e90d6a698cead7c19b55fcede44587aa7f Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 6 Apr 2020 20:02:12 +0200 Subject: [PATCH 138/148] client/input: remove unused GetCheckPassword --- client/input/input.go | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/client/input/input.go b/client/input/input.go index 73dd822fd36..50a87c21514 100644 --- a/client/input/input.go +++ b/client/input/input.go @@ -2,7 +2,6 @@ package input import ( "bufio" - "errors" "fmt" "os" "strings" @@ -36,31 +35,6 @@ func GetPassword(prompt string, buf *bufio.Reader) (pass string, err error) { return pass, nil } -// GetCheckPassword will prompt for a password twice to verify they -// match (for creating a new password). -// It enforces the password length. Only parses password once if -// input is piped in. -func GetCheckPassword(prompt, prompt2 string, buf *bufio.Reader) (string, error) { - // simple read on no-tty - if !inputIsTty() { - return GetPassword(prompt, buf) - } - - // TODO: own function??? - pass, err := GetPassword(prompt, buf) - if err != nil { - return "", err - } - pass2, err := GetPassword(prompt2, buf) - if err != nil { - return "", err - } - if pass != pass2 { - return "", errors.New("passphrases don't match") - } - return pass, nil -} - // GetConfirmation will request user give the confirmation from stdin. // "y", "Y", "yes", "YES", and "Yes" all count as confirmations. // If the input is not recognized, it returns false and a nil error. From fc81ef952303ef3c023f33c5a9a5232c3a3dd677 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 6 Apr 2020 20:05:42 +0200 Subject: [PATCH 139/148] client/input: remove redundant PrintPrefixed function --- client/input/input.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/client/input/input.go b/client/input/input.go index 50a87c21514..8cfcc97fbb8 100644 --- a/client/input/input.go +++ b/client/input/input.go @@ -64,7 +64,7 @@ func GetConfirmation(prompt string, buf *bufio.Reader) (bool, error) { // GetString simply returns the trimmed string output of a given reader. func GetString(prompt string, buf *bufio.Reader) (string, error) { if inputIsTty() && prompt != "" { - PrintPrefixed(prompt) + fmt.Fprintf(os.Stderr, "> %s\n", prompt) } out, err := readLineFromBuf(buf) @@ -91,9 +91,3 @@ func readLineFromBuf(buf *bufio.Reader) (string, error) { } return strings.TrimSpace(pass), nil } - -// PrintPrefixed prints a string with > prefixed for use in prompts. -func PrintPrefixed(msg string) { - msg = fmt.Sprintf("> %s\n", msg) - fmt.Fprint(os.Stderr, msg) -} From cbfbc3eb6140dc2ad443393462a903db7549c174 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 6 Apr 2020 20:11:39 +0200 Subject: [PATCH 140/148] client/input: GetConfirmation takes io.Writer to communicate with users. --- client/input/input.go | 5 +++-- client/keys/add.go | 2 +- client/keys/delete.go | 2 +- client/keys/migrate.go | 2 +- client/keys/mnemonic.go | 2 +- client/tx/tx.go | 2 +- x/auth/client/tx.go | 2 +- 7 files changed, 9 insertions(+), 8 deletions(-) diff --git a/client/input/input.go b/client/input/input.go index 8cfcc97fbb8..4e36bbe5192 100644 --- a/client/input/input.go +++ b/client/input/input.go @@ -3,6 +3,7 @@ package input import ( "bufio" "fmt" + "io" "os" "strings" @@ -38,12 +39,12 @@ func GetPassword(prompt string, buf *bufio.Reader) (pass string, err error) { // GetConfirmation will request user give the confirmation from stdin. // "y", "Y", "yes", "YES", and "Yes" all count as confirmations. // If the input is not recognized, it returns false and a nil error. -func GetConfirmation(prompt string, buf *bufio.Reader) (bool, error) { +func GetConfirmation(prompt string, r *bufio.Reader, w io.Writer) (bool, error) { if inputIsTty() { fmt.Printf("%s [y/N]: ", prompt) } - response, err := readLineFromBuf(buf) + response, err := readLineFromBuf(r) if err != nil { return false, err } diff --git a/client/keys/add.go b/client/keys/add.go index 048ea48a05a..c6a396e5d3a 100644 --- a/client/keys/add.go +++ b/client/keys/add.go @@ -127,7 +127,7 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *buf _, err = kb.Key(name) if err == nil { // account exists, ask for user confirmation - response, err2 := input.GetConfirmation(fmt.Sprintf("override the existing name %s", name), inBuf) + response, err2 := input.GetConfirmation(fmt.Sprintf("override the existing name %s", name), inBuf, cmd.ErrOrStderr()) if err2 != nil { return err2 } diff --git a/client/keys/delete.go b/client/keys/delete.go index ce0f8f4dc6c..e0501969998 100644 --- a/client/keys/delete.go +++ b/client/keys/delete.go @@ -55,7 +55,7 @@ func runDeleteCmd(cmd *cobra.Command, args []string) error { // confirm deletion, unless -y is passed if !viper.GetBool(flagYes) { - if yes, err := input.GetConfirmation("Key reference will be deleted. Continue?", buf); err != nil { + if yes, err := input.GetConfirmation("Key reference will be deleted. Continue?", buf, cmd.ErrOrStderr()); err != nil { return err } else if !yes { continue diff --git a/client/keys/migrate.go b/client/keys/migrate.go index 12dc313e5f2..8d52bd83faf 100644 --- a/client/keys/migrate.go +++ b/client/keys/migrate.go @@ -95,7 +95,7 @@ func runMigrateCmd(cmd *cobra.Command, args []string) error { cmd.PrintErrf("Migrating key: '%s (%s)' ...\n", key.GetName(), keyType) // allow user to skip migrating specific keys - ok, err := input.GetConfirmation("Skip key migration?", buf) + ok, err := input.GetConfirmation("Skip key migration?", buf, cmd.ErrOrStderr()) if err != nil { return err } diff --git a/client/keys/mnemonic.go b/client/keys/mnemonic.go index e665130ee4c..66b3b17d027 100644 --- a/client/keys/mnemonic.go +++ b/client/keys/mnemonic.go @@ -46,7 +46,7 @@ func runMnemonicCmd(cmd *cobra.Command, args []string) error { if len(inputEntropy) < 43 { return fmt.Errorf("256-bits is 43 characters in Base-64, and 100 in Base-6. You entered %v, and probably want more", len(inputEntropy)) } - conf, err := input.GetConfirmation(fmt.Sprintf("> Input length: %d", len(inputEntropy)), buf) + conf, err := input.GetConfirmation(fmt.Sprintf("> Input length: %d", len(inputEntropy)), buf, cmd.ErrOrStderr()) if err != nil { return err } diff --git a/client/tx/tx.go b/client/tx/tx.go index 8a57e6f1f11..0cd4e71f3dd 100644 --- a/client/tx/tx.go +++ b/client/tx/tx.go @@ -127,7 +127,7 @@ func BroadcastTx(ctx context.CLIContext, txf Factory, msgs ...sdk.Msg) error { _, _ = fmt.Fprintf(os.Stderr, "%s\n\n", out) buf := bufio.NewReader(os.Stdin) - ok, err := input.GetConfirmation("confirm transaction before signing and broadcasting", buf) + ok, err := input.GetConfirmation("confirm transaction before signing and broadcasting", buf, os.Stderr) if err != nil || !ok { _, _ = fmt.Fprintf(os.Stderr, "%s\n", "cancelled transaction") return err diff --git a/x/auth/client/tx.go b/x/auth/client/tx.go index 95c6a0b9a1c..cc04cd73084 100644 --- a/x/auth/client/tx.go +++ b/x/auth/client/tx.go @@ -97,7 +97,7 @@ func CompleteAndBroadcastTxCLI(txBldr authtypes.TxBuilder, cliCtx context.CLICon _, _ = fmt.Fprintf(os.Stderr, "%s\n\n", json) buf := bufio.NewReader(os.Stdin) - ok, err := input.GetConfirmation("confirm transaction before signing and broadcasting", buf) + ok, err := input.GetConfirmation("confirm transaction before signing and broadcasting", buf, os.Stderr) if err != nil || !ok { _, _ = fmt.Fprintf(os.Stderr, "%s\n", "cancelled transaction") return err From e40b978efb5a7cf6e80a2ed4aa3b682f5fc48ce0 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 6 Apr 2020 21:32:16 +0200 Subject: [PATCH 141/148] Simplify, don't include app name in keyring directories --- crypto/keyring/keyring.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 27fc3db78a3..96a18cef63a 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -35,9 +35,9 @@ const ( ) const ( - keyringDirNameFmt = "keyring-%s" - testKeyringDirNameFmt = "keyring-test-%s" - passKeyringPrefix = keyringDirNameFmt + keyringFileDirName = "keyring-file" + keyringTestDirName = "keyring-test" + passKeyringPrefix = "keyring-%s" ) var ( @@ -548,7 +548,7 @@ func lkbToKeyringConfig(appName, dir string, buf io.Reader, test bool) keyring.C return keyring.Config{ AllowedBackends: []keyring.BackendType{keyring.FileBackend}, ServiceName: appName, - FileDir: filepath.Join(dir, fmt.Sprintf(testKeyringDirNameFmt, appName)), + FileDir: filepath.Join(dir, keyringTestDirName), FilePasswordFunc: func(_ string) (string, error) { return "test", nil }, @@ -581,7 +581,7 @@ func newPassBackendKeyringConfig(appName, dir string, _ io.Reader) keyring.Confi } func newFileBackendKeyringConfig(name, dir string, buf io.Reader) keyring.Config { - fileDir := filepath.Join(dir, fmt.Sprintf(keyringDirNameFmt, name)) + fileDir := filepath.Join(dir, keyringFileDirName) return keyring.Config{ AllowedBackends: []keyring.BackendType{keyring.FileBackend}, ServiceName: name, From 2a674f713f15f636094c86ea03fcba85b99486de Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 6 Apr 2020 21:48:17 +0200 Subject: [PATCH 142/148] tidy up, few more tests --- crypto/keyring/keyring.go | 48 +++++++++++++++++----------------- crypto/keyring/keyring_test.go | 13 +++++++++ 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/crypto/keyring/keyring.go b/crypto/keyring/keyring.go index 96a18cef63a..de834428792 100644 --- a/crypto/keyring/keyring.go +++ b/crypto/keyring/keyring.go @@ -110,6 +110,15 @@ type Exporter interface { ExportPrivKeyArmorByAddress(address sdk.Address, encryptPassphrase string) (armor string, err error) } +// Option overrides keyring configuration options. +type Option func(options *Options) + +//Options define the options of the Keyring +type Options struct { + SupportedAlgos SigningAlgoList + SupportedAlgosLedger SigningAlgoList +} + // 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. @@ -131,11 +140,11 @@ func New( case BackendMemory: return NewInMemory(opts...), err case BackendTest: - db, err = keyring.Open(lkbToKeyringConfig(appName, rootDir, nil, true)) + db, err = keyring.Open(newTestBackendKeyringConfig(appName, rootDir)) case BackendFile: db, err = keyring.Open(newFileBackendKeyringConfig(appName, rootDir, userInput)) case BackendOS: - db, err = keyring.Open(lkbToKeyringConfig(appName, rootDir, userInput, false)) + db, err = keyring.Open(newOSBackendKeyringConfig(appName, rootDir, userInput)) case BackendKWallet: db, err = keyring.Open(newKWalletBackendKeyringConfig(appName, rootDir, userInput)) case BackendPass: @@ -507,15 +516,6 @@ func (ks keystore) Key(uid string) (Info, error) { return unmarshalInfo(bs.Data) } -// Option overrides keyring configuration options. -type Option func(options *Options) - -//Options define the options of the Keyring -type Options struct { - SupportedAlgos SigningAlgoList - SupportedAlgosLedger 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. @@ -543,18 +543,7 @@ func SignWithLedger(info Info, msg []byte) (sig []byte, pub tmcrypto.PubKey, err return sig, priv.PubKey(), nil } -func lkbToKeyringConfig(appName, dir string, buf io.Reader, test bool) keyring.Config { - if test { - return keyring.Config{ - AllowedBackends: []keyring.BackendType{keyring.FileBackend}, - ServiceName: appName, - FileDir: filepath.Join(dir, keyringTestDirName), - FilePasswordFunc: func(_ string) (string, error) { - return "test", nil - }, - } - } - +func newOSBackendKeyringConfig(appName, dir string, buf io.Reader) keyring.Config { return keyring.Config{ ServiceName: appName, FileDir: dir, @@ -562,6 +551,17 @@ func lkbToKeyringConfig(appName, dir string, buf io.Reader, test bool) keyring.C } } +func newTestBackendKeyringConfig(appName, dir string) keyring.Config { + return keyring.Config{ + AllowedBackends: []keyring.BackendType{keyring.FileBackend}, + ServiceName: appName, + FileDir: filepath.Join(dir, keyringTestDirName), + FilePasswordFunc: func(_ string) (string, error) { + return "test", nil + }, + } +} + func newKWalletBackendKeyringConfig(appName, _ string, _ io.Reader) keyring.Config { return keyring.Config{ AllowedBackends: []keyring.BackendType{keyring.KWalletBackend}, @@ -571,7 +571,7 @@ func newKWalletBackendKeyringConfig(appName, _ string, _ io.Reader) keyring.Conf } } -func newPassBackendKeyringConfig(appName, dir string, _ io.Reader) keyring.Config { +func newPassBackendKeyringConfig(appName, _ string, _ io.Reader) keyring.Config { prefix := fmt.Sprintf(passKeyringPrefix, appName) return keyring.Config{ AllowedBackends: []keyring.BackendType{keyring.PassBackend}, diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index abfe8e4a273..2f153303f66 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -6,6 +6,7 @@ import ( "strings" "testing" + "github.com/99designs/keyring" "github.com/cosmos/go-bip39" "github.com/stretchr/testify/require" tmcrypto "github.com/tendermint/tendermint/crypto" @@ -1282,6 +1283,18 @@ func TestAltKeyring_ConstructorSupportedAlgos(t *testing.T) { require.NoError(t, err) } +func TestBackendConfigConstructors(t *testing.T) { + backend := newKWalletBackendKeyringConfig("test", "", nil) + require.Equal(t, []keyring.BackendType{keyring.KWalletBackend}, backend.AllowedBackends) + require.Equal(t, "kdewallet", backend.ServiceName) + require.Equal(t, "test", backend.KWalletAppID) + + backend = newPassBackendKeyringConfig("test", "directory", nil) + require.Equal(t, []keyring.BackendType{keyring.PassBackend}, backend.AllowedBackends) + require.Equal(t, "test", backend.ServiceName) + require.Equal(t, "keyring-test", backend.PassPrefix) +} + func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { require.Equal(t, key.GetName(), mnemonic.GetName()) require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) From 67eb0381a623ce362503f45ddb1b9feef3662065 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 6 Apr 2020 23:46:46 +0200 Subject: [PATCH 143/148] Split tests that require ledger support --- crypto/keyring/keyring_ledger_test.go | 128 ++++++++++++++++++++++++++ crypto/keyring/keyring_test.go | 112 ---------------------- 2 files changed, 128 insertions(+), 112 deletions(-) create mode 100644 crypto/keyring/keyring_ledger_test.go diff --git a/crypto/keyring/keyring_ledger_test.go b/crypto/keyring/keyring_ledger_test.go new file mode 100644 index 00000000000..7c4bc37b7f1 --- /dev/null +++ b/crypto/keyring/keyring_ledger_test.go @@ -0,0 +1,128 @@ +//+build ledger test_ledger_mock + +package keyring + +import ( + "bytes" + "testing" + + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/tests" + "github.com/cosmos/cosmos-sdk/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func TestInMemoryCreateLedger(t *testing.T) { + kb := NewInMemory() + + ledger, 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) + 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() + pk, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) + require.NoError(t, err) + require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) + + // Check that restoring the key gets the same results + restoredKey, err := kb.Key("some_account") + require.NoError(t, err) + require.NotNil(t, restoredKey) + require.Equal(t, "some_account", restoredKey.GetName()) + require.Equal(t, TypeLedger, restoredKey.GetType()) + pubKey = restoredKey.GetPubKey() + pk, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) + require.NoError(t, err) + require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) + + path, err := restoredKey.GetPath() + require.NoError(t, err) + require.Equal(t, "44'/118'/3'/0/1", path.String()) +} + +// TestSignVerify does some detailed checks on how we sign and validate +// signatures +func TestSignVerifyKeyRingWithLedger(t *testing.T) { + dir, cleanup := tests.NewTestCaseDir(t) + t.Cleanup(cleanup) + kb, err := New("keybasename", "test", dir, nil) + require.NoError(t, err) + + i1, 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()) + + d1 := []byte("my first message") + s1, pub1, err := kb.Sign("key", d1) + require.NoError(t, err) + + s2, pub2, err := SignWithLedger(i1, 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) + require.True(t, pub1.VerifyBytes(d1, s1)) + require.True(t, i1.GetPubKey().VerifyBytes(d1, s1)) + require.True(t, bytes.Equal(s1, s2)) + + localInfo, _, err := kb.NewMnemonic("test", English, types.FullFundraiserPath, hd.Secp256k1) + require.NoError(t, err) + _, _, err = SignWithLedger(localInfo, d1) + require.Error(t, err) + require.Equal(t, "not a ledger object", err.Error()) +} + +func TestAltKeyring_SaveLedgerKey(t *testing.T) { + dir, clean := tests.NewTestCaseDir(t) + t.Cleanup(clean) + + keyring, err := New(t.Name(), BackendTest, dir, nil) + require.NoError(t, err) + + // Test unsupported Algo + _, err = keyring.SaveLedgerKey("key", notSupportedAlgo{}, "cosmos", 118, 0, 0) + require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) + + ledger, err := keyring.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") + return + } + // The mock is available, check that the address is correct + require.Equal(t, "some_account", ledger.GetName()) + pubKey := ledger.GetPubKey() + pk, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) + require.NoError(t, err) + require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) + + // Check that restoring the key gets the same results + restoredKey, err := keyring.Key("some_account") + require.NoError(t, err) + require.NotNil(t, restoredKey) + require.Equal(t, "some_account", restoredKey.GetName()) + require.Equal(t, TypeLedger, restoredKey.GetType()) + pubKey = restoredKey.GetPubKey() + pk, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) + require.NoError(t, err) + require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) + + path, err := restoredKey.GetPath() + require.NoError(t, err) + require.Equal(t, "44'/118'/3'/0/1", path.String()) +} diff --git a/crypto/keyring/keyring_test.go b/crypto/keyring/keyring_test.go index 2f153303f66..566fd2c87ba 100644 --- a/crypto/keyring/keyring_test.go +++ b/crypto/keyring/keyring_test.go @@ -1,7 +1,6 @@ package keyring import ( - "bytes" "fmt" "strings" "testing" @@ -131,42 +130,6 @@ func TestKeyManagementKeyRing(t *testing.T) { require.NoError(t, kb.Delete(n2)) } -// TestSignVerify does some detailed checks on how we sign and validate -// signatures -func TestSignVerifyKeyRingWithLedger(t *testing.T) { - dir, cleanup := tests.NewTestCaseDir(t) - t.Cleanup(cleanup) - kb, err := New("keybasename", "test", dir, nil) - require.NoError(t, err) - - i1, 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()) - - d1 := []byte("my first message") - s1, pub1, err := kb.Sign("key", d1) - require.NoError(t, err) - - s2, pub2, err := SignWithLedger(i1, d1) - require.NoError(t, err) - - require.Equal(t, i1.GetPubKey(), pub1) - require.Equal(t, i1.GetPubKey(), pub2) - require.True(t, pub1.VerifyBytes(d1, s1)) - require.True(t, i1.GetPubKey().VerifyBytes(d1, s1)) - require.True(t, bytes.Equal(s1, s2)) - - localInfo, _, err := kb.NewMnemonic("test", English, types.FullFundraiserPath, hd.Secp256k1) - require.NoError(t, err) - _, _, err = SignWithLedger(localInfo, d1) - require.Error(t, err) - require.Equal(t, "not a ledger object", err.Error()) -} - func TestSignVerifyKeyRing(t *testing.T) { dir, cleanup := tests.NewTestCaseDir(t) t.Cleanup(cleanup) @@ -446,41 +409,6 @@ func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { require.Equal(t, "Invalid mnemonic", err.Error()) } -func TestInMemoryCreateLedger(t *testing.T) { - kb := NewInMemory() - - ledger, 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) - 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() - pk, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) - require.NoError(t, err) - require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) - - // Check that restoring the key gets the same results - restoredKey, err := kb.Key("some_account") - require.NoError(t, err) - require.NotNil(t, restoredKey) - require.Equal(t, "some_account", restoredKey.GetName()) - require.Equal(t, TypeLedger, restoredKey.GetType()) - pubKey = restoredKey.GetPubKey() - pk, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) - require.NoError(t, err) - require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) - - path, err := restoredKey.GetPath() - require.NoError(t, err) - require.Equal(t, "44'/118'/3'/0/1", path.String()) -} - // TestInMemoryKeyManagement makes sure we can manipulate these keys well func TestInMemoryKeyManagement(t *testing.T) { // make the storage with reasonable defaults @@ -936,46 +864,6 @@ func TestAltKeyring_NewAccount(t *testing.T) { require.Len(t, list, 1) } -func TestAltKeyring_SaveLedgerKey(t *testing.T) { - dir, clean := tests.NewTestCaseDir(t) - t.Cleanup(clean) - - keyring, err := New(t.Name(), BackendTest, dir, nil) - require.NoError(t, err) - - // Test unsupported Algo - _, err = keyring.SaveLedgerKey("key", notSupportedAlgo{}, "cosmos", 118, 0, 0) - require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) - - ledger, err := keyring.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") - return - } - // The mock is available, check that the address is correct - require.Equal(t, "some_account", ledger.GetName()) - pubKey := ledger.GetPubKey() - pk, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) - require.NoError(t, err) - require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) - - // Check that restoring the key gets the same results - restoredKey, err := keyring.Key("some_account") - require.NoError(t, err) - require.NotNil(t, restoredKey) - require.Equal(t, "some_account", restoredKey.GetName()) - require.Equal(t, TypeLedger, restoredKey.GetType()) - pubKey = restoredKey.GetPubKey() - pk, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey) - require.NoError(t, err) - require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk) - - path, err := restoredKey.GetPath() - require.NoError(t, err) - require.Equal(t, "44'/118'/3'/0/1", path.String()) -} - func TestAltKeyring_Get(t *testing.T) { dir, clean := tests.NewTestCaseDir(t) t.Cleanup(clean) From 70ca9a71a52f716c0d8b2de626d44d5f54271c68 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Tue, 7 Apr 2020 12:54:38 +0200 Subject: [PATCH 144/148] Instantiate in-memory if --gen-only is passed --- client/context/context.go | 37 ++++++++++++++++++++++++---------- client/context/context_test.go | 28 +++++++++++++++++++++---- 2 files changed, 50 insertions(+), 15 deletions(-) diff --git a/client/context/context.go b/client/context/context.go index 5a332c0d62f..7bca8a6660b 100644 --- a/client/context/context.go +++ b/client/context/context.go @@ -26,6 +26,7 @@ type CLIContext struct { ChainID string Marshaler codec.Marshaler Input io.Reader + Keyring keyring.Keyring Output io.Writer OutputFormat string Height int64 @@ -57,8 +58,14 @@ func NewCLIContextWithInputAndFrom(input io.Reader, from string) CLIContext { var nodeURI string var rpc rpcclient.Client + homedir := viper.GetString(flags.FlagHome) genOnly := viper.GetBool(flags.FlagGenerateOnly) - fromAddress, fromName, err := GetFromFields(input, from, genOnly) + keyring, err := newKeyringFromFlags(viper.GetString(flags.FlagKeyringBackend), homedir, input, genOnly) + if err != nil { + panic(fmt.Errorf("couldn't acquire keyring: %v", err)) + } + + fromAddress, fromName, err := GetFromFields(keyring, from, genOnly) if err != nil { fmt.Printf("failed to get from fields: %v\n", err) os.Exit(1) @@ -83,9 +90,10 @@ func NewCLIContextWithInputAndFrom(input io.Reader, from string) CLIContext { Output: os.Stdout, NodeURI: nodeURI, From: viper.GetString(flags.FlagFrom), + Keyring: keyring, OutputFormat: viper.GetString(cli.OutputFlag), Height: viper.GetInt64(flags.FlagHeight), - HomeDir: viper.GetString(flags.FlagHome), + HomeDir: homedir, TrustNode: viper.GetBool(flags.FlagTrustNode), UseLedger: viper.GetBool(flags.FlagUseLedger), BroadcastMode: viper.GetString(flags.FlagBroadcastMode), @@ -128,6 +136,12 @@ func NewCLIContextWithInput(input io.Reader) CLIContext { return NewCLIContextWithInputAndFrom(input, viper.GetString(flags.FlagFrom)) } +// WithKeyring returns a copy of the context with an updated keyring. +func (ctx CLIContext) WithKeyring(k keyring.Keyring) CLIContext { + ctx.Keyring = k + return ctx +} + // WithInput returns a copy of the context with an updated input. func (ctx CLIContext) WithInput(r io.Reader) CLIContext { ctx.Input = r @@ -306,7 +320,7 @@ func (ctx CLIContext) PrintOutput(toPrint interface{}) error { // GetFromFields returns a from account address and Keybase name given either // an address or key name. If genOnly is true, only a valid Bech32 cosmos // address is returned. -func GetFromFields(input io.Reader, from string, genOnly bool) (sdk.AccAddress, string, error) { +func GetFromFields(kr keyring.Keyring, from string, genOnly bool) (sdk.AccAddress, string, error) { if from == "" { return nil, "", nil } @@ -320,20 +334,14 @@ func GetFromFields(input io.Reader, from string, genOnly bool) (sdk.AccAddress, return addr, "", nil } - keybase, err := keyring.New(sdk.KeyringServiceName(), - viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), input) - if err != nil { - return nil, "", err - } - var info keyring.Info if addr, err := sdk.AccAddressFromBech32(from); err == nil { - info, err = keybase.KeyByAddress(addr) + info, err = kr.KeyByAddress(addr) if err != nil { return nil, "", err } } else { - info, err = keybase.Key(from) + info, err = kr.Key(from) if err != nil { return nil, "", err } @@ -341,3 +349,10 @@ func GetFromFields(input io.Reader, from string, genOnly bool) (sdk.AccAddress, return info.GetAddress(), info.GetName(), nil } + +func newKeyringFromFlags(backend, homedir string, input io.Reader, genOnly bool) (keyring.Keyring, error) { + if genOnly { + return keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, homedir, input) + } + return keyring.New(sdk.KeyringServiceName(), backend, homedir, input) +} diff --git a/client/context/context_test.go b/client/context/context_test.go index 3b6ea0e71af..f1221a7fcfd 100644 --- a/client/context/context_test.go +++ b/client/context/context_test.go @@ -1,13 +1,16 @@ -package context +package context_test import ( + "os" "testing" + "github.com/cosmos/cosmos-sdk/crypto/keyring" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/spf13/viper" "github.com/stretchr/testify/require" + "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/flags" ) @@ -15,7 +18,7 @@ func TestCLIContext_WithOffline(t *testing.T) { viper.Set(flags.FlagOffline, true) viper.Set(flags.FlagNode, "tcp://localhost:26657") - ctx := NewCLIContext() + ctx := context.NewCLIContext() require.True(t, ctx.Offline) require.Nil(t, ctx.Client) @@ -23,8 +26,9 @@ func TestCLIContext_WithOffline(t *testing.T) { viper.Set(flags.FlagOffline, false) viper.Set(flags.FlagNode, "tcp://localhost:26657") + viper.Set(flags.FlagKeyringBackend, keyring.BackendMemory) - ctx = NewCLIContext() + ctx = context.NewCLIContext() require.False(t, ctx.Offline) require.NotNil(t, ctx.Client) } @@ -59,10 +63,26 @@ func TestCLIContext_WithGenOnly(t *testing.T) { for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { - ctx := NewCLIContextWithFrom(tt.from) + ctx := context.NewCLIContextWithFrom(tt.from) require.Equal(t, tt.expectedFromAddr, ctx.FromAddress) require.Equal(t, tt.expectedFromName, ctx.FromName) }) } } + +func TestCLIContext_WithKeyring(t *testing.T) { + viper.Set(flags.FlagGenerateOnly, true) + ctx := context.NewCLIContextWithFrom("cosmos1q7380u26f7ntke3facjmynajs4umlr329vr4ja") + require.NotNil(t, ctx.Keyring) + kr := ctx.Keyring + ctx = ctx.WithKeyring(nil) + require.Nil(t, ctx.Keyring) + ctx = ctx.WithKeyring(kr) + require.Equal(t, kr, ctx.Keyring) +} + +func TestMain(m *testing.M) { + viper.Set(flags.FlagKeyringBackend, keyring.BackendMemory) + os.Exit(m.Run()) +} From 4b8d3a1a76ee0dafe2fcb4fdfa071f0385aeb2ad Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Tue, 7 Apr 2020 15:29:00 +0200 Subject: [PATCH 145/148] Fallback to in memory backend --- client/context/context.go | 7 ++++++- client/context/context_test.go | 1 - 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/client/context/context.go b/client/context/context.go index 7bca8a6660b..c908a2044a8 100644 --- a/client/context/context.go +++ b/client/context/context.go @@ -60,7 +60,12 @@ func NewCLIContextWithInputAndFrom(input io.Reader, from string) CLIContext { homedir := viper.GetString(flags.FlagHome) genOnly := viper.GetBool(flags.FlagGenerateOnly) - keyring, err := newKeyringFromFlags(viper.GetString(flags.FlagKeyringBackend), homedir, input, genOnly) + backend := viper.GetString(flags.FlagKeyringBackend) + if len(backend) == 0 { + backend = keyring.BackendMemory + } + + keyring, err := newKeyringFromFlags(backend, homedir, input, genOnly) if err != nil { panic(fmt.Errorf("couldn't acquire keyring: %v", err)) } diff --git a/client/context/context_test.go b/client/context/context_test.go index f1221a7fcfd..7429fc18605 100644 --- a/client/context/context_test.go +++ b/client/context/context_test.go @@ -26,7 +26,6 @@ func TestCLIContext_WithOffline(t *testing.T) { viper.Set(flags.FlagOffline, false) viper.Set(flags.FlagNode, "tcp://localhost:26657") - viper.Set(flags.FlagKeyringBackend, keyring.BackendMemory) ctx = context.NewCLIContext() require.False(t, ctx.Offline) From e72eb951fb06d752c37d7e6842945ca0ef3c42bb Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Tue, 7 Apr 2020 20:34:51 +0200 Subject: [PATCH 146/148] Update CHANGELOG [skip ci] --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f1fc9c7bbd..a5188f54fac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -83,6 +83,11 @@ to now accept a `codec.JSONMarshaler` for modular serialization of genesis state - `NewKeyring()` now accepts a new backend: `MemoryBackend`. - `New()` has been renamed to`NewLegacy()`, which now returns a `LegacyKeybase` type that only allows migration of keys from the legacy keybase to a new keyring. * (client/keys) [\#5889](https://github.com/cosmos/cosmos-sdk/pull/5889) Rename `NewKeyBaseFromDir()` -> `NewLegacyKeyBaseFromDir()`. +* (crypto/keyring) [\#5904](https://github.com/cosmos/cosmos-sdk/pull/5904) `Keybase` -> `Keyring` interfaces migration. `LegacyKeybase` interface is added in order +to guarantee limited backward compatibility with the old Keybase interface for the sole purpose of migrating keys across the new keyring backends. Plus, the package +and the new keyring no longer depends on the sdk.Config singleton. +* (crypto/keys) [\#5904](https://github.com/cosmos/cosmos-sdk/pull/5904) `crypto/keys/hd` moved to `crypto/hd`. +* (client/input) [\#5904](https://github.com/cosmos/cosmos-sdk/pull/5904) Removal of unnecessary `GetCheckPassword`, `PrintPrefixed` functions. ### Features From 640cbecc9171d58213b0e2041d39ee22c6ee476e Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Tue, 7 Apr 2020 21:44:32 +0200 Subject: [PATCH 147/148] Sort changelog, tidy up --- CHANGELOG.md | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 528a6208f16..80c9156f7ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,24 +70,22 @@ and provided directly the IAVL store. * (modules) [\#5572](https://github.com/cosmos/cosmos-sdk/pull/5572) Move account balance logic and APIs from `x/auth` to `x/bank`. * (types) [\#5533](https://github.com/cosmos/cosmos-sdk/pull/5533) Refactored `AppModuleBasic` and `AppModuleGenesis` to now accept a `codec.JSONMarshaler` for modular serialization of genesis state. -* (crypto/keyring) [\#5735](https://github.com/cosmos/cosmos-sdk/pull/5735) Keyring's `Update()` function is now no-op. * (types/rest) [\#5779](https://github.com/cosmos/cosmos-sdk/pull/5779) Drop unused Parse{Int64OrReturnBadRequest,QueryParamBool}() functions. * (keys) [\#5820](https://github.com/cosmos/cosmos-sdk/pull/5820/) Removed method CloseDB from Keybase interface. * (baseapp) [\#5837](https://github.com/cosmos/cosmos-sdk/issues/5837) Transaction simulation now returns a `SimulationResponse` which contains the `GasInfo` and `Result` from the execution. -* (crypto/keyring) [\#5866](https://github.com/cosmos/cosmos-sdk/pull/5866) Move `Keyring` and `Keybase` implementations and their associated types from `crypto/keys/` to `crypto/keyring/`. -* (crypto) [\#5880](https://github.com/cosmos/cosmos-sdk/pull/5880) Merge `crypto/keys/mintkey` into `crypto`. -* (crypto/keyring) [\#5858](https://github.com/cosmos/cosmos-sdk/pull/5858) Make Keyring store keys by name and address's hexbytes representation. -* (crypto/keyring) [\#5889](https://github.com/cosmos/cosmos-sdk/pull/5889) Deprecate old keybase implementation: - - Remove `Update` from the `Keybase` interface. - - `NewKeyring()` now accepts a new backend: `MemoryBackend`. - - `New()` has been renamed to`NewLegacy()`, which now returns a `LegacyKeybase` type that only allows migration of keys from the legacy keybase to a new keyring. -* (client/keys) [\#5889](https://github.com/cosmos/cosmos-sdk/pull/5889) Rename `NewKeyBaseFromDir()` -> `NewLegacyKeyBaseFromDir()`. -* (crypto/keyring) [\#5904](https://github.com/cosmos/cosmos-sdk/pull/5904) `Keybase` -> `Keyring` interfaces migration. `LegacyKeybase` interface is added in order -to guarantee limited backward compatibility with the old Keybase interface for the sole purpose of migrating keys across the new keyring backends. Plus, the package -and the new keyring no longer depends on the sdk.Config singleton. -* (crypto/keys) [\#5904](https://github.com/cosmos/cosmos-sdk/pull/5904) `crypto/keys/hd` moved to `crypto/hd`. * (client/input) [\#5904](https://github.com/cosmos/cosmos-sdk/pull/5904) Removal of unnecessary `GetCheckPassword`, `PrintPrefixed` functions. +* (client/keys) [\#5889](https://github.com/cosmos/cosmos-sdk/pull/5889) Rename `NewKeyBaseFromDir()` -> `NewLegacyKeyBaseFromDir()`. +* (crypto) [\#5880](https://github.com/cosmos/cosmos-sdk/pull/5880) Merge `crypto/keys/mintkey` into `crypto`. +* (crypto/hd) [\#5904](https://github.com/cosmos/cosmos-sdk/pull/5904) `crypto/keys/hd` moved to `crypto/hd`. +* (crypto/keyring): + - [\#5866](https://github.com/cosmos/cosmos-sdk/pull/5866) Rename `crypto/keys/` to `crypto/keyring/`. + - [\#5904](https://github.com/cosmos/cosmos-sdk/pull/5904) `Keybase` -> `Keyring` interfaces migration. `LegacyKeybase` interface is added in order +to guarantee limited backward compatibility with the old Keybase interface for the sole purpose of migrating keys across the new keyring backends. `NewLegacy` +constructor is provided [\#5889](https://github.com/cosmos/cosmos-sdk/pull/5889) to allow for smooth migration of keys from the legacy LevelDB based implementation +to new keyring backends. Plus, the package and the new keyring no longer depends on the sdk.Config singleton. Please consult the package documentation for more +information on how to implement the new `Keyring` interface. + - [\#5858](https://github.com/cosmos/cosmos-sdk/pull/5858) Make Keyring store keys by name and address's hexbytes representation. ### Features @@ -97,8 +95,8 @@ and the new keyring no longer depends on the sdk.Config singleton. * (types) [\#5741](https://github.com/cosmos/cosmos-sdk/issues/5741) Prevent ChainAnteDecorators() from panicking when empty AnteDecorator slice is supplied. * (modules) [\#5569](https://github.com/cosmos/cosmos-sdk/issues/5569) `InitGenesis`, for the relevant modules, now ensures module accounts exist. -* (crypto/keyring) [\#5844](https://github.com/cosmos/cosmos-sdk/pull/5844) Keybase/Keyring `Sign()` methods no longer decode amino signatures -when method receivers are offline/multisig keys. +* (crypto/keyring) [\#5844](https://github.com/cosmos/cosmos-sdk/pull/5844) `Keyring.Sign()` methods no longer decode amino signatures when method receivers +are offline/multisig keys. * (x/auth) [\#5892](https://github.com/cosmos/cosmos-sdk/pull/5892) Add `RegisterKeyTypeCodec` to register new types (eg. keys) to the `auth` module internal amino codec. * (rest) [\#5906](https://github.com/cosmos/cosmos-sdk/pull/5906) Fix an issue that make some REST calls panic when sending From 2d0f3c3a5f923b1900233903a6fee36fcccfafd5 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Tue, 7 Apr 2020 21:58:09 +0200 Subject: [PATCH 148/148] Fix CHANGELOG formatting --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80c9156f7ef..7775e032659 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -79,13 +79,13 @@ to now accept a `codec.JSONMarshaler` for modular serialization of genesis state * (crypto) [\#5880](https://github.com/cosmos/cosmos-sdk/pull/5880) Merge `crypto/keys/mintkey` into `crypto`. * (crypto/hd) [\#5904](https://github.com/cosmos/cosmos-sdk/pull/5904) `crypto/keys/hd` moved to `crypto/hd`. * (crypto/keyring): - - [\#5866](https://github.com/cosmos/cosmos-sdk/pull/5866) Rename `crypto/keys/` to `crypto/keyring/`. - - [\#5904](https://github.com/cosmos/cosmos-sdk/pull/5904) `Keybase` -> `Keyring` interfaces migration. `LegacyKeybase` interface is added in order + - [\#5866](https://github.com/cosmos/cosmos-sdk/pull/5866) Rename `crypto/keys/` to `crypto/keyring/`. + - [\#5904](https://github.com/cosmos/cosmos-sdk/pull/5904) `Keybase` -> `Keyring` interfaces migration. `LegacyKeybase` interface is added in order to guarantee limited backward compatibility with the old Keybase interface for the sole purpose of migrating keys across the new keyring backends. `NewLegacy` constructor is provided [\#5889](https://github.com/cosmos/cosmos-sdk/pull/5889) to allow for smooth migration of keys from the legacy LevelDB based implementation to new keyring backends. Plus, the package and the new keyring no longer depends on the sdk.Config singleton. Please consult the package documentation for more information on how to implement the new `Keyring` interface. - - [\#5858](https://github.com/cosmos/cosmos-sdk/pull/5858) Make Keyring store keys by name and address's hexbytes representation. + - [\#5858](https://github.com/cosmos/cosmos-sdk/pull/5858) Make Keyring store keys by name and address's hexbytes representation. ### Features