crypto/keyring: change addrKey to store chain-agnostic addresses (#5858)
Keyrings store keys by name and hexbytes representation of address. This turns keyring internal storage more chain-agnostic and types.Config independent. Obsolete Keybase internal state representation is not affected.
This commit is contained in:
parent
b6c45b76a7
commit
db76afe840
@ -69,13 +69,14 @@ 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/keys) [\#5735](https://github.com/cosmos/cosmos-sdk/pull/5735) Keyring's `Update()` function is now no-op.
|
||||
* (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/keys) [\#5866](https://github.com/cosmos/cosmos-sdk/pull/5866) Move `Keyring` and `Keybase` implementations and their associated types from `crypto/keys/` to `crypto/keybase/`.
|
||||
* (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.
|
||||
|
||||
### Features
|
||||
|
||||
@ -85,7 +86,7 @@ to now accept a `codec.JSONMarshaler` for modular serialization of genesis state
|
||||
|
||||
* (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/keys) [\#5844](https://github.com/cosmos/cosmos-sdk/pull/5844) Keybase/Keyring `Sign()` methods no longer decode amino signatures
|
||||
* (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.
|
||||
|
||||
### State Machine Breaking
|
||||
|
||||
@ -291,7 +291,7 @@ func printCreate(cmd *cobra.Command, info keyring.Info, showMnemonic bool, mnemo
|
||||
switch output {
|
||||
case OutputFormatText:
|
||||
cmd.PrintErrln()
|
||||
printKeyInfo(info, keyring.Bech32KeyOutput)
|
||||
printKeyInfo(cmd.OutOrStdout(), info, keyring.Bech32KeyOutput)
|
||||
|
||||
// print mnemonic unless requested not to.
|
||||
if showMnemonic {
|
||||
|
||||
@ -36,12 +36,12 @@ func runListCmd(cmd *cobra.Command, _ []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd.SetOut(cmd.OutOrStdout())
|
||||
if !viper.GetBool(flagListNames) {
|
||||
printInfos(infos)
|
||||
printInfos(cmd.OutOrStdout(), infos)
|
||||
return nil
|
||||
}
|
||||
|
||||
cmd.SetOut(cmd.OutOrStdout())
|
||||
for _, info := range infos {
|
||||
cmd.Println(info.GetName())
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
@ -83,38 +84,39 @@ hexadecimal into bech32 cosmos prefixed format and vice versa.
|
||||
return cmd
|
||||
}
|
||||
|
||||
func parseKey(_ *cobra.Command, args []string) error {
|
||||
func parseKey(cmd *cobra.Command, args []string) error {
|
||||
addr := strings.TrimSpace(args[0])
|
||||
outstream := cmd.OutOrStdout()
|
||||
if len(addr) == 0 {
|
||||
return errors.New("couldn't parse empty input")
|
||||
}
|
||||
if !(runFromBech32(addr) || runFromHex(addr)) {
|
||||
if !(runFromBech32(outstream, addr) || runFromHex(outstream, addr)) {
|
||||
return errors.New("couldn't find valid bech32 nor hex data")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// print info from bech32
|
||||
func runFromBech32(bech32str string) bool {
|
||||
func runFromBech32(w io.Writer, bech32str string) bool {
|
||||
hrp, bz, err := bech32.DecodeAndConvert(bech32str)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
displayParseKeyInfo(newHexOutput(hrp, bz))
|
||||
displayParseKeyInfo(w, newHexOutput(hrp, bz))
|
||||
return true
|
||||
}
|
||||
|
||||
// print info from hex
|
||||
func runFromHex(hexstr string) bool {
|
||||
func runFromHex(w io.Writer, hexstr string) bool {
|
||||
bz, err := hex.DecodeString(hexstr)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
displayParseKeyInfo(newBech32Output(bz))
|
||||
displayParseKeyInfo(w, newBech32Output(bz))
|
||||
return true
|
||||
}
|
||||
|
||||
func displayParseKeyInfo(stringer fmt.Stringer) {
|
||||
func displayParseKeyInfo(w io.Writer, stringer fmt.Stringer) {
|
||||
var out []byte
|
||||
var err error
|
||||
|
||||
@ -136,5 +138,5 @@ func displayParseKeyInfo(stringer fmt.Stringer) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(string(out))
|
||||
fmt.Fprintln(w, string(out))
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ func TestParseKey(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
require.Equal(t, tt.wantErr, parseKey(nil, tt.args) != nil)
|
||||
require.Equal(t, tt.wantErr, parseKey(ParseKeyStringCommand(), tt.args) != nil)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,10 +35,10 @@ const (
|
||||
// ShowKeysCmd shows key information for a given key name.
|
||||
func ShowKeysCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "show [name [name...]]",
|
||||
Short: "Show key info for the given name",
|
||||
Long: `Return public details of a single local key. If multiple names are
|
||||
provided, then an ephemeral multisig key will be created under the name "multi"
|
||||
Use: "show [name_or_address [name_or_address...]]",
|
||||
Short: "Retrieve key information by name or address",
|
||||
Long: `Display keys details. If multiple names or addresses are provided,
|
||||
then an ephemeral multisig key will be created under the name "multi"
|
||||
consisting of all the keys provided by name and multisig threshold.`,
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
RunE: runShowCmd,
|
||||
@ -62,16 +62,16 @@ func runShowCmd(cmd *cobra.Command, args []string) (err error) {
|
||||
return err
|
||||
}
|
||||
if len(args) == 1 {
|
||||
info, err = kb.Get(args[0])
|
||||
info, err = fetchKey(kb, args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("%s is not a valid name or address: %v", args[0], err)
|
||||
}
|
||||
} else {
|
||||
pks := make([]tmcrypto.PubKey, len(args))
|
||||
for i, keyName := range args {
|
||||
info, err := kb.Get(keyName)
|
||||
for i, keyref := range args {
|
||||
info, err := fetchKey(kb, keyref)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("%s is not a valid name or address: %v", keyref, err)
|
||||
}
|
||||
|
||||
pks[i] = info.GetPubKey()
|
||||
@ -112,11 +112,11 @@ func runShowCmd(cmd *cobra.Command, args []string) (err error) {
|
||||
|
||||
switch {
|
||||
case isShowAddr:
|
||||
printKeyAddress(info, bechKeyOut)
|
||||
printKeyAddress(cmd.OutOrStdout(), info, bechKeyOut)
|
||||
case isShowPubKey:
|
||||
printPubKey(info, bechKeyOut)
|
||||
printPubKey(cmd.OutOrStdout(), info, bechKeyOut)
|
||||
default:
|
||||
printKeyInfo(info, bechKeyOut)
|
||||
printKeyInfo(cmd.OutOrStdout(), info, bechKeyOut)
|
||||
}
|
||||
|
||||
if isShowDevice {
|
||||
@ -142,6 +142,22 @@ 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)
|
||||
if err != nil {
|
||||
accAddr, err := sdk.AccAddressFromBech32(keyref)
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
|
||||
info, err = kb.GetByAddress(accAddr)
|
||||
if err != nil {
|
||||
return info, errors.New("key not found")
|
||||
}
|
||||
}
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func validateMultisigThreshold(k, nKeys int) error {
|
||||
if k <= 0 {
|
||||
return fmt.Errorf("threshold must be a positive integer")
|
||||
|
||||
@ -38,8 +38,8 @@ func Test_runShowCmd(t *testing.T) {
|
||||
runningUnattended := isRunningUnattended()
|
||||
cmd := ShowKeysCmd()
|
||||
mockIn, _, _ := tests.ApplyMockIO(cmd)
|
||||
require.EqualError(t, runShowCmd(cmd, []string{"invalid"}), "The specified item could not be found in the keyring")
|
||||
require.EqualError(t, runShowCmd(cmd, []string{"invalid1", "invalid2"}), "The specified item could not be found in the keyring")
|
||||
require.EqualError(t, runShowCmd(cmd, []string{"invalid"}), "invalid is not a valid name or address: decoding bech32 failed: invalid bech32 string length 7")
|
||||
require.EqualError(t, runShowCmd(cmd, []string{"invalid1", "invalid2"}), "invalid1 is not a valid name or address: decoding bech32 failed: invalid index of 1")
|
||||
|
||||
// Prepare a key base
|
||||
// Now add a temporary keybase
|
||||
@ -78,7 +78,13 @@ func Test_runShowCmd(t *testing.T) {
|
||||
if runningUnattended {
|
||||
mockIn.Reset("testpass1\n")
|
||||
}
|
||||
|
||||
// try fetch by name
|
||||
require.NoError(t, runShowCmd(cmd, []string{fakeKeyName1}))
|
||||
// try fetch by addr
|
||||
info, err := kb.Get(fakeKeyName1)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, runShowCmd(cmd, []string{info.GetAddress().String()}))
|
||||
|
||||
// Now try multisig key - set bech to acc
|
||||
viper.Set(FlagBechPrefix, sdk.PrefixAccount)
|
||||
|
||||
@ -2,12 +2,13 @@ package keys
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/99designs/keyring"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
cryptokeyring "github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
@ -37,7 +38,7 @@ func getLazyKeyBaseFromDir(rootDir string, opts ...cryptokeyring.KeybaseOption)
|
||||
return cryptokeyring.New(defaultKeyDBName, filepath.Join(rootDir, "keys"), opts...), nil
|
||||
}
|
||||
|
||||
func printKeyInfo(keyInfo cryptokeyring.Info, bechKeyOut bechKeyOutFn) {
|
||||
func printKeyInfo(w io.Writer, keyInfo cryptokeyring.Info, bechKeyOut bechKeyOutFn) {
|
||||
ko, err := bechKeyOut(keyInfo)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -45,7 +46,7 @@ func printKeyInfo(keyInfo cryptokeyring.Info, bechKeyOut bechKeyOutFn) {
|
||||
|
||||
switch viper.Get(cli.OutputFlag) {
|
||||
case OutputFormatText:
|
||||
printTextInfos([]cryptokeyring.KeyOutput{ko})
|
||||
printTextInfos(w, []cryptokeyring.KeyOutput{ko})
|
||||
|
||||
case OutputFormatJSON:
|
||||
var out []byte
|
||||
@ -59,11 +60,11 @@ func printKeyInfo(keyInfo cryptokeyring.Info, bechKeyOut bechKeyOutFn) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(string(out))
|
||||
fmt.Fprintln(w, string(out))
|
||||
}
|
||||
}
|
||||
|
||||
func printInfos(infos []cryptokeyring.Info) {
|
||||
func printInfos(w io.Writer, infos []cryptokeyring.Info) {
|
||||
kos, err := cryptokeyring.Bech32KeysOutput(infos)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -71,7 +72,7 @@ func printInfos(infos []cryptokeyring.Info) {
|
||||
|
||||
switch viper.Get(cli.OutputFlag) {
|
||||
case OutputFormatText:
|
||||
printTextInfos(kos)
|
||||
printTextInfos(w, kos)
|
||||
|
||||
case OutputFormatJSON:
|
||||
var out []byte
|
||||
@ -86,34 +87,34 @@ func printInfos(infos []cryptokeyring.Info) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("%s", out)
|
||||
fmt.Fprintf(w, "%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func printTextInfos(kos []cryptokeyring.KeyOutput) {
|
||||
func printTextInfos(w io.Writer, kos []cryptokeyring.KeyOutput) {
|
||||
out, err := yaml.Marshal(&kos)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
fmt.Fprintln(w, string(out))
|
||||
}
|
||||
|
||||
func printKeyAddress(info cryptokeyring.Info, bechKeyOut bechKeyOutFn) {
|
||||
func printKeyAddress(w io.Writer, info cryptokeyring.Info, bechKeyOut bechKeyOutFn) {
|
||||
ko, err := bechKeyOut(info)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(ko.Address)
|
||||
fmt.Fprintln(w, ko.Address)
|
||||
}
|
||||
|
||||
func printPubKey(info cryptokeyring.Info, bechKeyOut bechKeyOutFn) {
|
||||
func printPubKey(w io.Writer, info cryptokeyring.Info, bechKeyOut bechKeyOutFn) {
|
||||
ko, err := bechKeyOut(info)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(ko.PubKey)
|
||||
fmt.Fprintln(w, ko.PubKey)
|
||||
}
|
||||
|
||||
func isRunningUnattended() bool {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package keyring
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
@ -126,7 +127,7 @@ func (kb dbKeybase) Get(name string) (Info, error) {
|
||||
// GetByAddress returns Info based on a provided AccAddress. An error is returned
|
||||
// if the address does not exist.
|
||||
func (kb dbKeybase) GetByAddress(address types.AccAddress) (Info, error) {
|
||||
ik, err := kb.db.Get(addrKey(address))
|
||||
ik, err := kb.db.Get(addrStringKey(address))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -344,7 +345,7 @@ func (kb dbKeybase) Delete(name, passphrase string, skipPass bool) error {
|
||||
batch := kb.db.NewBatch()
|
||||
defer batch.Close()
|
||||
|
||||
batch.Delete(addrKey(info.GetAddress()))
|
||||
batch.Delete(addrStringKey(info.GetAddress()))
|
||||
batch.Delete(infoKey(name))
|
||||
|
||||
return batch.WriteSync()
|
||||
@ -414,13 +415,18 @@ func (kb dbKeybase) writeInfo(name string, info Info) {
|
||||
kb.db.SetSync(key, serializedInfo)
|
||||
|
||||
// store a pointer to the infokey by address for fast lookup
|
||||
kb.db.SetSync(addrKey(info.GetAddress()), key)
|
||||
kb.db.SetSync(addrStringKey(info.GetAddress()), key)
|
||||
}
|
||||
|
||||
func addrKey(address types.AccAddress) []byte {
|
||||
// this is to be removed together with dbKeybase and the old Keybase interface
|
||||
func addrStringKey(address types.AccAddress) []byte {
|
||||
return []byte(fmt.Sprintf("%s.%s", address.String(), addressSuffix))
|
||||
}
|
||||
|
||||
func addrHexKey(address types.AccAddress) []byte {
|
||||
return []byte(fmt.Sprintf("%s.%s", hex.EncodeToString(address.Bytes()), addressSuffix))
|
||||
}
|
||||
|
||||
func infoKey(name string) []byte {
|
||||
return []byte(fmt.Sprintf("%s.%s", name, infoSuffix))
|
||||
}
|
||||
|
||||
@ -178,7 +178,7 @@ func (kb keyringKeybase) Get(name string) (Info, error) {
|
||||
|
||||
// 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(addrKey(address)))
|
||||
ik, err := kb.db.Get(string(addrHexKey(address)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -313,7 +313,7 @@ func (kb keyringKeybase) Import(name string, armor string) error {
|
||||
kb.writeInfo(name, info)
|
||||
|
||||
err = kb.db.Set(keyring.Item{
|
||||
Key: string(addrKey(info.GetAddress())),
|
||||
Key: string(addrHexKey(info.GetAddress())),
|
||||
Data: infoKey(name),
|
||||
})
|
||||
if err != nil {
|
||||
@ -401,7 +401,7 @@ func (kb keyringKeybase) Delete(name, _ string, _ bool) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = kb.db.Remove(string(addrKey(info.GetAddress())))
|
||||
err = kb.db.Remove(string(addrHexKey(info.GetAddress())))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -454,7 +454,7 @@ func (kb keyringKeybase) writeInfo(name string, info Info) {
|
||||
}
|
||||
|
||||
err = kb.db.Set(keyring.Item{
|
||||
Key: string(addrKey(info.GetAddress())),
|
||||
Key: string(addrHexKey(info.GetAddress())),
|
||||
Data: key,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user