From 9311f9efd033837fc172de9381703f1f78f55245 Mon Sep 17 00:00:00 2001 From: Austin Abell Date: Wed, 13 Nov 2019 12:00:21 -0500 Subject: [PATCH] Update keybase back to cosmos-sdk with support (#147) * Migrate keybase back to Cosmos-sdk using temporary fork * Cleaned up other affected code * Change to updated tendermint * fmt * Change auth codec update * clean up codec registration to respective packages * Fix import fmt * Remove no longer necessary replace * Fix function comment --- app/ethermint.go | 4 + cmd/emintcli/keys.go | 68 +++++ cmd/emintcli/main.go | 12 +- cmd/emintd/genaccounts.go | 2 +- cmd/emintd/gentx.go | 302 --------------------- cmd/emintd/main.go | 10 +- crypto/keys/codec.go | 25 -- crypto/keys/keybase.go | 512 ------------------------------------ crypto/keys/keys.go | 13 - crypto/keys/lazy_keybase.go | 222 ---------------- crypto/keys/output.go | 111 -------- crypto/keys/types.go | 156 ----------- crypto/keys/types_test.go | 46 ---- crypto/secp256k1.go | 10 + go.mod | 13 +- go.sum | 25 +- keys/add.go | 258 ------------------ keys/add_test.go | 48 ---- keys/codec.go | 23 -- keys/root.go | 34 --- keys/show.go | 132 ---------- keys/show_test.go | 51 ---- keys/utils.go | 167 ------------ rpc/config.go | 2 +- rpc/eth_api.go | 4 +- types/account.go | 5 + types/codec.go | 7 +- x/evm/client/cli/tx.go | 71 +---- x/evm/client/utils/tx.go | 344 ------------------------ x/evm/types/codec.go | 2 - 30 files changed, 137 insertions(+), 2542 deletions(-) create mode 100644 cmd/emintcli/keys.go delete mode 100644 cmd/emintd/gentx.go delete mode 100644 crypto/keys/codec.go delete mode 100644 crypto/keys/keybase.go delete mode 100644 crypto/keys/keys.go delete mode 100644 crypto/keys/lazy_keybase.go delete mode 100644 crypto/keys/output.go delete mode 100644 crypto/keys/types.go delete mode 100644 crypto/keys/types_test.go delete mode 100644 keys/add.go delete mode 100644 keys/add_test.go delete mode 100644 keys/codec.go delete mode 100644 keys/root.go delete mode 100644 keys/show.go delete mode 100644 keys/show_test.go delete mode 100644 keys/utils.go delete mode 100644 x/evm/client/utils/tx.go diff --git a/app/ethermint.go b/app/ethermint.go index ad43b68e..31d71e06 100644 --- a/app/ethermint.go +++ b/app/ethermint.go @@ -4,10 +4,12 @@ import ( "encoding/json" "os" + emintcrypto "github.com/cosmos/ethermint/crypto" "github.com/cosmos/ethermint/x/evm" bam "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec" + cryptokeys "github.com/cosmos/cosmos-sdk/crypto/keys" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/version" @@ -76,8 +78,10 @@ func MakeCodec() *codec.Codec { var cdc = codec.New() ModuleBasics.RegisterCodec(cdc) + cryptokeys.RegisterCodec(cdc) // temporary sdk.RegisterCodec(cdc) codec.RegisterCrypto(cdc) + emintcrypto.RegisterCodec(cdc) eminttypes.RegisterCodec(cdc) return cdc diff --git a/cmd/emintcli/keys.go b/cmd/emintcli/keys.go new file mode 100644 index 00000000..42c0708e --- /dev/null +++ b/cmd/emintcli/keys.go @@ -0,0 +1,68 @@ +package main + +import ( + "github.com/cosmos/cosmos-sdk/client/flags" + clientkeys "github.com/cosmos/cosmos-sdk/client/keys" + "github.com/cosmos/cosmos-sdk/crypto/keys" + + emintCrypto "github.com/cosmos/ethermint/crypto" + tmcrypto "github.com/tendermint/tendermint/crypto" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +const ( + flagDryRun = "dry-run" +) + +// keyCommands registers a sub-tree of commands to interact with +// local private key storage. +func keyCommands() *cobra.Command { + cmd := &cobra.Command{ + Use: "keys", + Short: "Add or view local private keys", + Long: `Keys allows you to manage your local keystore for tendermint. + + These keys may be in any format supported by go-crypto and can be + used by light-clients, full nodes, or any other application that + needs to sign with a private key.`, + } + addCmd := clientkeys.AddKeyCommand() + addCmd.RunE = runAddCmd + cmd.AddCommand( + clientkeys.MnemonicKeyCommand(), + addCmd, + clientkeys.ExportKeyCommand(), + clientkeys.ImportKeyCommand(), + clientkeys.ListKeysCmd(), + clientkeys.ShowKeysCmd(), + flags.LineBreak, + clientkeys.DeleteKeyCommand(), + clientkeys.UpdateKeyCommand(), + clientkeys.ParseKeyStringCommand(), + clientkeys.MigrateCommand(), + ) + return cmd +} + +func getKeybase(dryrun bool) (keys.Keybase, error) { + if dryrun { + return keys.NewInMemory(keys.WithKeygenFunc(ethermintKeygenFunc)), nil + } + + return clientkeys.NewKeyBaseFromHomeFlag(keys.WithKeygenFunc(ethermintKeygenFunc)) +} + +func runAddCmd(cmd *cobra.Command, args []string) error { + kb, err := getKeybase(viper.GetBool(flagDryRun)) + if err != nil { + return err + } + + return clientkeys.RunAddCmd(cmd, args, kb) +} + +func ethermintKeygenFunc(bz [32]byte) tmcrypto.PrivKey { + return emintCrypto.PrivKeySecp256k1(bz[:]) +} diff --git a/cmd/emintcli/main.go b/cmd/emintcli/main.go index b6a88855..078d2c96 100644 --- a/cmd/emintcli/main.go +++ b/cmd/emintcli/main.go @@ -4,19 +4,20 @@ import ( "os" "path" + emintapp "github.com/cosmos/ethermint/app" "github.com/cosmos/ethermint/rpc" + "github.com/tendermint/go-amino" "github.com/cosmos/cosmos-sdk/client" + clientkeys "github.com/cosmos/cosmos-sdk/client/keys" sdkrpc "github.com/cosmos/cosmos-sdk/client/rpc" + cryptokeys "github.com/cosmos/cosmos-sdk/crypto/keys" sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - emintkeys "github.com/cosmos/ethermint/keys" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli" - emintapp "github.com/cosmos/ethermint/app" "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/tendermint/tendermint/libs/cli" @@ -27,7 +28,8 @@ func main() { cdc := emintapp.MakeCodec() - authtypes.ModuleCdc = cdc + cryptokeys.CryptoCdc = cdc + clientkeys.KeysCdc = cdc // Read in the configuration file for the sdk config := sdk.GetConfig() @@ -56,7 +58,7 @@ func main() { // TODO: Set up rest routes (if included, different from web3 api) rpc.Web3RpcCmd(cdc), client.LineBreak, - emintkeys.Commands(), + keyCommands(), client.LineBreak, ) diff --git a/cmd/emintd/genaccounts.go b/cmd/emintd/genaccounts.go index b7ae1c7c..9b1a23bf 100644 --- a/cmd/emintd/genaccounts.go +++ b/cmd/emintd/genaccounts.go @@ -9,6 +9,7 @@ import ( "github.com/tendermint/tendermint/libs/cli" + "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/server" sdk "github.com/cosmos/cosmos-sdk/types" @@ -16,7 +17,6 @@ import ( authexported "github.com/cosmos/cosmos-sdk/x/auth/exported" authvesting "github.com/cosmos/cosmos-sdk/x/auth/vesting" "github.com/cosmos/cosmos-sdk/x/genutil" - "github.com/cosmos/ethermint/keys" ethermint "github.com/cosmos/ethermint/types" ) diff --git a/cmd/emintd/gentx.go b/cmd/emintd/gentx.go deleted file mode 100644 index 1d1ba232..00000000 --- a/cmd/emintd/gentx.go +++ /dev/null @@ -1,302 +0,0 @@ -package main - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - - "github.com/pkg/errors" - - "github.com/spf13/cobra" - flag "github.com/spf13/pflag" - "github.com/spf13/viper" - - cfg "github.com/tendermint/tendermint/config" - "github.com/tendermint/tendermint/crypto" - "github.com/tendermint/tendermint/libs/common" - tmtypes "github.com/tendermint/tendermint/types" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/codec" - kbkeys "github.com/cosmos/cosmos-sdk/crypto/keys" - "github.com/cosmos/cosmos-sdk/server" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/module" - "github.com/cosmos/cosmos-sdk/x/auth" - "github.com/cosmos/cosmos-sdk/x/auth/client/utils" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - "github.com/cosmos/cosmos-sdk/x/genutil" - "github.com/cosmos/cosmos-sdk/x/genutil/types" - - "github.com/cosmos/ethermint/keys" - clientutils "github.com/cosmos/ethermint/x/evm/client/utils" -) - -// StakingMsgBuildingHelpers helpers for message building gen-tx command -type StakingMsgBuildingHelpers interface { - CreateValidatorMsgHelpers(ipDefault string) (fs *flag.FlagSet, nodeIDFlag, pubkeyFlag, amountFlag, defaultsDesc string) - PrepareFlagsForTxCreateValidator(config *cfg.Config, nodeID, chainID string, valPubKey crypto.PubKey) - BuildCreateValidatorMsg(cliCtx context.CLIContext, txBldr auth.TxBuilder) (auth.TxBuilder, sdk.Msg, error) -} - -// GenTxCmd builds the application's gentx command. -// nolint: errcheck -func GenTxCmd(ctx *server.Context, cdc *codec.Codec, mbm module.BasicManager, smbh StakingMsgBuildingHelpers, - genAccIterator types.GenesisAccountsIterator, defaultNodeHome, defaultCLIHome string) *cobra.Command { - - ipDefault, _ := server.ExternalIP() - fsCreateValidator, flagNodeID, flagPubKey, flagAmount, defaultsDesc := smbh.CreateValidatorMsgHelpers(ipDefault) - - cmd := &cobra.Command{ - Use: "gentx", - Short: "Generate a genesis tx carrying a self delegation", - Args: cobra.NoArgs, - Long: fmt.Sprintf(`This command is an alias of the 'tx create-validator' command'. - - It creates a genesis transaction to create a validator. - The following default parameters are included: - %s`, defaultsDesc), - - RunE: func(cmd *cobra.Command, args []string) error { - - config := ctx.Config - config.SetRoot(viper.GetString(client.FlagHome)) - nodeID, valPubKey, err := genutil.InitializeNodeValidatorFiles(ctx.Config) - if err != nil { - return errors.Wrap(err, "failed to initialize node validator files") - } - - // Read --nodeID, if empty take it from priv_validator.json - if nodeIDString := viper.GetString(flagNodeID); nodeIDString != "" { - nodeID = nodeIDString - } - // Read --pubkey, if empty take it from priv_validator.json - if valPubKeyString := viper.GetString(flagPubKey); valPubKeyString != "" { - valPubKey, err = sdk.GetConsPubKeyBech32(valPubKeyString) - if err != nil { - return errors.Wrap(err, "failed to get consensus node public key") - } - } - - genDoc, err := tmtypes.GenesisDocFromFile(config.GenesisFile()) - if err != nil { - return errors.Wrapf(err, "failed to read genesis doc file %s", config.GenesisFile()) - } - - var genesisState map[string]json.RawMessage - if err = cdc.UnmarshalJSON(genDoc.AppState, &genesisState); err != nil { - return errors.Wrap(err, "failed to unmarshal genesis state") - } - - if err = mbm.ValidateGenesis(genesisState); err != nil { - return errors.Wrap(err, "failed to validate genesis state") - } - - // * Necessary to change keybase here - kb, err := keys.NewKeyBaseFromDir(viper.GetString(flagClientHome)) - if err != nil { - return errors.Wrap(err, "failed to initialize keybase") - } - - name := viper.GetString(client.FlagName) - key, err := kb.Get(name) - if err != nil { - return errors.Wrap(err, "failed to read from keybase") - } - - // Set flags for creating gentx - viper.Set(client.FlagHome, viper.GetString(flagClientHome)) - smbh.PrepareFlagsForTxCreateValidator(config, nodeID, genDoc.ChainID, valPubKey) - - // Fetch the amount of coins staked - amount := viper.GetString(flagAmount) - coins, err := sdk.ParseCoins(amount) - if err != nil { - return errors.Wrap(err, "failed to parse coins") - } - - err = genutil.ValidateAccountInGenesis(genesisState, genAccIterator, key.GetAddress(), coins, cdc) - if err != nil { - return errors.Wrap(err, "failed to validate account in genesis") - } - - txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)).WithKeybase(kb) - cliCtx := clientutils.NewETHCLIContext().WithCodec(cdc) - - // Set the generate-only flag here after the CLI context has - // been created. This allows the from name/key to be correctly populated. - // - // TODO: Consider removing the manual setting of generate-only in - // favor of a 'gentx' flag in the create-validator command. - viper.Set(client.FlagGenerateOnly, true) - - // create a 'create-validator' message - txBldr, msg, err := smbh.BuildCreateValidatorMsg(cliCtx, txBldr) - if err != nil { - return errors.Wrap(err, "failed to build create-validator message") - } - - info, err := kb.Get(name) - if err != nil { - return errors.Wrap(err, "failed to read from tx builder keybase") - } - - if info.GetType() == kbkeys.TypeOffline || info.GetType() == kbkeys.TypeMulti { - fmt.Println("Offline key passed in. Use `tx sign` command to sign:") - return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}) - } - - // write the unsigned transaction to the buffer - w := bytes.NewBuffer([]byte{}) - cliCtx = cliCtx.WithOutput(w) - - if err = utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg}); err != nil { - return errors.Wrap(err, "failed to print unsigned std tx") - } - - // read the transaction - stdTx, err := readUnsignedGenTxFile(cdc, w) - if err != nil { - return errors.Wrap(err, "failed to read unsigned gen tx file") - } - - // * Function needed to be overriden for signStdTx function using default keybase - // sign the transaction and write it to the output file - signedTx, err := signStdTx(txBldr, cliCtx, name, stdTx, false, true) - if err != nil { - return errors.Wrap(err, "failed to sign std tx") - } - - // Fetch output file name - outputDocument := viper.GetString(client.FlagOutputDocument) - if outputDocument == "" { - outputDocument, err = makeOutputFilepath(config.RootDir, nodeID) - if err != nil { - return errors.Wrap(err, "failed to create output file path") - } - } - - if err := writeSignedGenTx(cdc, outputDocument, signedTx); err != nil { - return errors.Wrap(err, "failed to write signed gen tx") - } - - fmt.Fprintf(os.Stderr, "Genesis transaction written to %q\n", outputDocument) - return nil - - }, - } - - cmd.Flags().String(client.FlagHome, defaultNodeHome, "node's home directory") - cmd.Flags().String(flagClientHome, defaultCLIHome, "client's home directory") - cmd.Flags().String(client.FlagName, "", "name of private key with which to sign the gentx") - cmd.Flags().String(client.FlagOutputDocument, "", - "write the genesis transaction JSON document to the given file instead of the default location") - cmd.Flags().AddFlagSet(fsCreateValidator) - - if err := cmd.MarkFlagRequired(client.FlagName); err != nil { - panic(err) - } - - return cmd -} - -func makeOutputFilepath(rootDir, nodeID string) (string, error) { - writePath := filepath.Join(rootDir, "config", "gentx") - if err := common.EnsureDir(writePath, 0700); err != nil { - return "", err - } - return filepath.Join(writePath, fmt.Sprintf("gentx-%v.json", nodeID)), nil -} - -func readUnsignedGenTxFile(cdc *codec.Codec, r io.Reader) (auth.StdTx, error) { - var stdTx auth.StdTx - bytes, err := ioutil.ReadAll(r) - if err != nil { - return stdTx, err - } - err = cdc.UnmarshalJSON(bytes, &stdTx) - return stdTx, err -} - -func writeSignedGenTx(cdc *codec.Codec, outputDocument string, tx auth.StdTx) error { - outputFile, err := os.OpenFile(outputDocument, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0600) - if err != nil { - return err - } - defer func() { - if err := outputFile.Close(); err != nil { - panic(err) - } - }() - json, err := cdc.MarshalJSON(tx) - if err != nil { - return err - } - _, err = fmt.Fprintf(outputFile, "%s\n", json) - return err -} - -// SignStdTx appends a signature to a StdTx and returns a copy of it. If appendSig -// is false, it replaces the signatures already attached with the new signature. -// Don't perform online validation or lookups if offline is true. -func signStdTx( - txBldr authtypes.TxBuilder, cliCtx context.CLIContext, name string, - stdTx authtypes.StdTx, appendSig bool, offline bool, -) (authtypes.StdTx, error) { - - var signedStdTx authtypes.StdTx - - info, err := txBldr.Keybase().Get(name) - if err != nil { - return signedStdTx, err - } - - addr := info.GetPubKey().Address() - - // check whether the address is a signer - if !isTxSigner(sdk.AccAddress(addr), stdTx.GetSigners()) { - return signedStdTx, fmt.Errorf("%s: %s", errors.New("tx intended signer does not match the given signer"), name) - } - - if !offline { - txBldr, err = populateAccountFromState(txBldr, cliCtx, sdk.AccAddress(addr)) - if err != nil { - return signedStdTx, err - } - } - - // * Switched to use Ethermint keybase - passphrase, err := keys.GetPassphrase(name) - if err != nil { - return signedStdTx, err - } - - return txBldr.SignStdTx(name, passphrase, stdTx, appendSig) -} - -func populateAccountFromState( - txBldr authtypes.TxBuilder, cliCtx context.CLIContext, addr sdk.AccAddress, -) (authtypes.TxBuilder, error) { - - num, seq, err := authtypes.NewAccountRetriever(cliCtx).GetAccountNumberSequence(addr) - if err != nil { - return txBldr, err - } - - return txBldr.WithAccountNumber(num).WithSequence(seq), nil -} - -func isTxSigner(user sdk.AccAddress, signers []sdk.AccAddress) bool { - for _, s := range signers { - if bytes.Equal(user.Bytes(), s.Bytes()) { - return true - } - } - - return false -} diff --git a/cmd/emintd/main.go b/cmd/emintd/main.go index eed5d4aa..f5f497d5 100644 --- a/cmd/emintd/main.go +++ b/cmd/emintd/main.go @@ -8,12 +8,13 @@ import ( "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" + clientkeys "github.com/cosmos/cosmos-sdk/client/keys" + cryptokeys "github.com/cosmos/cosmos-sdk/crypto/keys" "github.com/cosmos/cosmos-sdk/server" "github.com/cosmos/cosmos-sdk/store" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - genutil "github.com/cosmos/cosmos-sdk/x/genutil" + "github.com/cosmos/cosmos-sdk/x/genutil" genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" "github.com/cosmos/cosmos-sdk/x/staking" @@ -36,9 +37,10 @@ func main() { cdc := emintapp.MakeCodec() + cryptokeys.CryptoCdc = cdc genutil.ModuleCdc = cdc genutiltypes.ModuleCdc = cdc - authtypes.ModuleCdc = cdc + clientkeys.KeysCdc = cdc config := sdk.GetConfig() config.SetBech32PrefixForAccount(sdk.Bech32PrefixAccAddr, sdk.Bech32PrefixAccPub) @@ -57,7 +59,7 @@ func main() { rootCmd.AddCommand( withChainIDValidation(genutilcli.InitCmd(ctx, cdc, emintapp.ModuleBasics, emintapp.DefaultNodeHome)), genutilcli.CollectGenTxsCmd(ctx, cdc, auth.GenesisAccountIterator{}, emintapp.DefaultNodeHome), - GenTxCmd( + genutilcli.GenTxCmd( ctx, cdc, emintapp.ModuleBasics, staking.AppModuleBasic{}, auth.GenesisAccountIterator{}, emintapp.DefaultNodeHome, emintapp.DefaultCLIHome, ), genutilcli.ValidateGenesisCmd(ctx, cdc, emintapp.ModuleBasics), diff --git a/crypto/keys/codec.go b/crypto/keys/codec.go deleted file mode 100644 index 02cb1760..00000000 --- a/crypto/keys/codec.go +++ /dev/null @@ -1,25 +0,0 @@ -package keys - -import ( - cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" - - "github.com/cosmos/cosmos-sdk/codec" - cosmosKeys "github.com/cosmos/cosmos-sdk/crypto/keys" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" - emintCrypto "github.com/cosmos/ethermint/crypto" -) - -var cdc *codec.Codec - -func init() { - cdc = codec.New() - cryptoAmino.RegisterAmino(cdc) - cdc.RegisterInterface((*cosmosKeys.Info)(nil), nil) - emintCrypto.RegisterCodec(cdc) - cdc.RegisterConcrete(hd.BIP44Params{}, "crypto/keys/hd/BIP44Params", nil) - cdc.RegisterConcrete(localInfo{}, "crypto/keys/localInfo", nil) - cdc.RegisterConcrete(ledgerInfo{}, "crypto/keys/ledgerInfo", nil) - cdc.RegisterConcrete(offlineInfo{}, "crypto/keys/offlineInfo", nil) - // cdc.RegisterConcrete(multiInfo{}, "crypto/keys/multiInfo", nil) - cdc.Seal() -} diff --git a/crypto/keys/keybase.go b/crypto/keys/keybase.go deleted file mode 100644 index 2f8d617f..00000000 --- a/crypto/keys/keybase.go +++ /dev/null @@ -1,512 +0,0 @@ -package keys - -import ( - "bufio" - "fmt" - "os" - "reflect" - "strings" - - "github.com/pkg/errors" - - "github.com/cosmos/cosmos-sdk/crypto" - cosmosKeys "github.com/cosmos/cosmos-sdk/crypto/keys" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" - "github.com/cosmos/cosmos-sdk/crypto/keys/keyerror" - "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/ethermint/crypto/keys/mintkey" - - bip39 "github.com/cosmos/go-bip39" - - emintCrypto "github.com/cosmos/ethermint/crypto" - tmcrypto "github.com/tendermint/tendermint/crypto" - cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino" - dbm "github.com/tendermint/tm-db" -) - -var _ cosmosKeys.Keybase = dbKeybase{} - -// Language is a language to create the BIP 39 mnemonic in. -// Currently, only english is supported though. -// Find a list of all supported languages in the BIP 39 spec (word lists). -type Language int - -//noinspection ALL -const ( - // English is the default language to create a mnemonic. - // It is the only supported language by this package. - English Language = iota + 1 - // Japanese is currently not supported. - Japanese - // Korean is currently not supported. - Korean - // Spanish is currently not supported. - Spanish - // ChineseSimplified is currently not supported. - ChineseSimplified - // ChineseTraditional is currently not supported. - ChineseTraditional - // French is currently not supported. - French - // Italian is currently not supported. - Italian - addressSuffix = "address" - infoSuffix = "info" -) - -const ( - // used for deriving seed from mnemonic - DefaultBIP39Passphrase = "" - - // bits of entropy to draw when creating a mnemonic - defaultEntropySize = 256 -) - -var ( - // ErrUnsupportedSigningAlgo is raised when the caller tries to use a - // different signing scheme than secp256k1. - ErrUnsupportedSigningAlgo = errors.New("unsupported signing algo: only secp256k1 is supported") - - // ErrUnsupportedLanguage is raised when the caller tries to use a - // different language than english for creating a mnemonic sentence. - ErrUnsupportedLanguage = errors.New("unsupported language: only english is supported") -) - -// dbKeybase combines encryption and storage implementation to provide -// a full-featured key manager -type dbKeybase struct { - db dbm.DB -} - -// newDbKeybase creates a new keybase instance using the passed DB for reading and writing keys. -func newDbKeybase(db dbm.DB) cosmosKeys.Keybase { - return dbKeybase{ - db: db, - } -} - -// NewInMemory creates a transient keybase on top of in-memory storage -// instance useful for testing purposes and on-the-fly key generation. -func NewInMemory() cosmosKeys.Keybase { return dbKeybase{dbm.NewMemDB()} } - -// CreateMnemonic generates a new key 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. -func (kb dbKeybase) CreateMnemonic(name string, language cosmosKeys.Language, passwd string, algo cosmosKeys.SigningAlgo) (info cosmosKeys.Info, mnemonic string, err error) { - if language != cosmosKeys.English { - return nil, "", ErrUnsupportedLanguage - } - if algo != Secp256k1 { - err = ErrUnsupportedSigningAlgo - return - } - - // 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 - } - mnemonic, err = bip39.NewMnemonic(entropy) - if err != nil { - return - } - - seed := bip39.NewSeed(mnemonic, DefaultBIP39Passphrase) - fullFundraiserPath := types.GetConfig().GetFullFundraiserPath() - info, err = kb.persistDerivedKey(seed, passwd, name, fullFundraiserPath) - return -} - -// CreateAccount converts a mnemonic to a private key and persists it, encrypted with the given password. -func (kb dbKeybase) CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd string, account uint32, index uint32) (cosmosKeys.Info, error) { - coinType := types.GetConfig().GetCoinType() - hdPath := hd.NewFundraiserParams(account, coinType, index) - return kb.Derive(name, mnemonic, bip39Passwd, encryptPasswd, *hdPath) -} - -func (kb dbKeybase) Derive(name, mnemonic, bip39Passphrase, encryptPasswd string, params hd.BIP44Params) (info cosmosKeys.Info, err error) { - seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase) - if err != nil { - return - } - - info, err = kb.persistDerivedKey(seed, encryptPasswd, name, params.String()) - return info, err -} - -// 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 dbKeybase) CreateLedger(name string, algo cosmosKeys.SigningAlgo, hrp string, account, index uint32) (cosmosKeys.Info, error) { - if algo != Secp256k1 { - 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 - } - pub := priv.PubKey() - - // Note: Once Cosmos App v1.3.1 is compulsory, it could be possible to check that pubkey and addr match - return kb.writeLedgerKey(name, pub, *hdPath), nil -} - -// CreateOffline creates a new reference to an offline keypair. It returns the -// created key info. -func (kb dbKeybase) CreateOffline(name string, pub tmcrypto.PubKey) (cosmosKeys.Info, error) { - return kb.writeOfflineKey(name, pub), nil -} - -// CreateMulti creates a new reference to a multisig (offline) keypair. It -// returns the created key info. -func (kb dbKeybase) CreateMulti(name string, pub tmcrypto.PubKey) (cosmosKeys.Info, error) { - return nil, nil -} - -func (kb *dbKeybase) persistDerivedKey(seed []byte, passwd, name, fullHdPath string) (info cosmosKeys.Info, err error) { - // create master key and derive first key: - masterPriv, ch := hd.ComputeMastersFromSeed(seed) - derivedPriv, err := hd.DerivePrivateKeyForPath(masterPriv, ch, fullHdPath) - if err != nil { - return - } - - // if we have a password, use it to encrypt the private key and store it - // else store the public key only - if passwd != "" { - info = kb.writeLocalKey(name, emintCrypto.PrivKeySecp256k1(derivedPriv[:]), passwd) - } else { - pubk := emintCrypto.PrivKeySecp256k1(derivedPriv[:]).PubKey() - info = kb.writeOfflineKey(name, pubk) - } - return info, nil -} - -// List returns the keys from storage in alphabetical order. -func (kb dbKeybase) List() ([]cosmosKeys.Info, error) { - var res []cosmosKeys.Info - iter := kb.db.Iterator(nil, nil) - defer iter.Close() - for ; iter.Valid(); iter.Next() { - key := string(iter.Key()) - - // need to include only keys in storage that have an info suffix - if strings.HasSuffix(key, infoSuffix) { - info, err := readInfo(iter.Value()) - if err != nil { - return nil, err - } - res = append(res, info) - } - } - return res, nil -} - -// Get returns the public information about one key. -func (kb dbKeybase) Get(name string) (cosmosKeys.Info, error) { - bs := kb.db.Get(infoKey(name)) - if len(bs) == 0 { - return nil, keyerror.NewErrKeyNotFound(name) - } - return readInfo(bs) -} - -func (kb dbKeybase) GetByAddress(address types.AccAddress) (cosmosKeys.Info, error) { - ik := kb.db.Get(addrKey(address)) - if len(ik) == 0 { - return nil, fmt.Errorf("key with address %s not found", address) - } - bs := kb.db.Get(ik) - return readInfo(bs) -} - -// Sign signs the msg with the named key. -// It returns an error if the key doesn't exist or the decryption fails. -func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig []byte, pub tmcrypto.PubKey, err error) { - info, err := kb.Get(name) - if err != nil { - return - } - - var priv tmcrypto.PrivKey - - switch info := info.(type) { - case localInfo: - if info.PrivKeyArmor == "" { - err = fmt.Errorf("private key not available") - return - } - - priv, err = mintkey.UnarmorDecryptPrivKey(info.PrivKeyArmor, passphrase) - if err != nil { - return nil, nil, err - } - - case ledgerInfo: - priv, err = crypto.NewPrivKeyLedgerSecp256k1Unsafe(info.Path) - if err != nil { - return - } - - // case offlineInfo, multiInfo: - case offlineInfo: - _, err := fmt.Fprintf(os.Stderr, "Message to sign:\n\n%s\n", msg) - if err != nil { - return nil, nil, err - } - - buf := bufio.NewReader(os.Stdin) - _, err = fmt.Fprintf(os.Stderr, "\nEnter Amino-encoded signature:\n") - if err != nil { - return nil, nil, err - } - - // Will block until user inputs the signature - signed, err := buf.ReadString('\n') - if err != nil { - return nil, nil, err - } - - if err := cdc.UnmarshalBinaryLengthPrefixed([]byte(signed), sig); err != nil { - return nil, nil, errors.Wrap(err, "failed to decode signature") - } - - return sig, info.GetPubKey(), nil - } - - sig, err = priv.Sign(msg) - if err != nil { - return nil, nil, err - } - - pub = priv.PubKey() - return sig, pub, nil -} - -func (kb dbKeybase) ExportPrivateKeyObject(name string, passphrase string) (tmcrypto.PrivKey, error) { - info, err := kb.Get(name) - if err != nil { - return nil, err - } - - var priv tmcrypto.PrivKey - - switch info := info.(type) { - case localInfo: - if info.PrivKeyArmor == "" { - err = fmt.Errorf("private key not available") - return nil, err - } - priv, err = mintkey.UnarmorDecryptPrivKey(info.PrivKeyArmor, passphrase) - if err != nil { - return nil, err - } - - // case ledgerInfo, offlineInfo, multiInfo: - case ledgerInfo, offlineInfo: - return nil, errors.New("only works on local private keys") - } - - return priv, nil -} - -func (kb dbKeybase) Export(name string) (armor string, err error) { - bz := kb.db.Get(infoKey(name)) - if bz == nil { - return "", fmt.Errorf("no key to export with name %s", name) - } - return mintkey.ArmorInfoBytes(bz), nil -} - -// ExportPubKey returns public keys in ASCII armored format. -// Retrieve a Info object by its name and return the public key in -// a portable format. -func (kb dbKeybase) ExportPubKey(name string) (armor string, err error) { - bz := kb.db.Get(infoKey(name)) - if bz == nil { - return "", fmt.Errorf("no key to export with name %s", name) - } - info, err := readInfo(bz) - if err != nil { - return - } - return mintkey.ArmorPubKeyBytes(info.GetPubKey().Bytes()), nil -} - -// ExportPrivKey returns a private key in ASCII armored format. -// It returns an error if the key does not exist or a wrong encryption passphrase is supplied. -func (kb dbKeybase) ExportPrivKey(name string, decryptPassphrase string, - encryptPassphrase string) (armor string, err error) { - priv, err := kb.ExportPrivateKeyObject(name, decryptPassphrase) - if err != nil { - return "", err - } - - return mintkey.EncryptArmorPrivKey(priv, encryptPassphrase), nil -} - -// 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. -func (kb dbKeybase) ImportPrivKey(name string, armor string, passphrase string) error { - if _, err := kb.Get(name); err == nil { - return errors.New("Cannot overwrite key " + name) - } - - privKey, err := mintkey.UnarmorDecryptPrivKey(armor, passphrase) - if err != nil { - return errors.Wrap(err, "couldn't import private key") - } - - kb.writeLocalKey(name, privKey, passphrase) - return nil -} - -func (kb dbKeybase) Import(name string, armor string) (err error) { - bz := kb.db.Get(infoKey(name)) - if len(bz) > 0 { - return errors.New("Cannot overwrite data for name " + name) - } - infoBytes, err := mintkey.UnarmorInfoBytes(armor) - if err != nil { - return - } - kb.db.Set(infoKey(name), infoBytes) - return nil -} - -// 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. -func (kb dbKeybase) ImportPubKey(name string, armor string) (err error) { - bz := kb.db.Get(infoKey(name)) - if len(bz) > 0 { - return errors.New("Cannot overwrite data for name " + name) - } - pubBytes, err := mintkey.UnarmorPubKeyBytes(armor) - if err != nil { - return - } - pubKey, err := cryptoAmino.PubKeyFromBytes(pubBytes) - if err != nil { - return - } - kb.writeOfflineKey(name, pubKey) - return -} - -// 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. -// Passphrase is ignored when deleting references to -// offline and Ledger / HW wallet keys. -func (kb dbKeybase) Delete(name, passphrase string, skipPass bool) error { - // verify we have the proper password before deleting - info, err := kb.Get(name) - if err != nil { - return err - } - if linfo, ok := info.(localInfo); ok && !skipPass { - if _, err = mintkey.UnarmorDecryptPrivKey(linfo.PrivKeyArmor, passphrase); err != nil { - return err - } - } - kb.db.DeleteSync(addrKey(info.GetAddress())) - kb.db.DeleteSync(infoKey(name)) - return nil -} - -// Update changes the passphrase with which an already stored key is -// encrypted. -// -// oldpass must be the current passphrase used for encryption, -// getNewpass is a function to get the passphrase to permanently replace -// the current passphrase -func (kb dbKeybase) Update(name, oldpass string, getNewpass func() (string, error)) error { - info, err := kb.Get(name) - if err != nil { - return err - } - switch info := info.(type) { - case localInfo: - key, err := mintkey.UnarmorDecryptPrivKey(info.PrivKeyArmor, oldpass) - if err != nil { - return err - } - newpass, err := getNewpass() - if err != nil { - return err - } - kb.writeLocalKey(name, key, newpass) - return nil - default: - return fmt.Errorf("locally stored key required. Received: %v", reflect.TypeOf(info).String()) - } -} - -// CloseDB releases the lock and closes the storage backend. -func (kb dbKeybase) CloseDB() { - kb.db.Close() -} - -func (kb dbKeybase) writeLocalKey(name string, priv tmcrypto.PrivKey, passphrase string) cosmosKeys.Info { - privkey, ok := priv.(emintCrypto.PrivKeySecp256k1) - if !ok { - panic(fmt.Sprintf("invalid private key type: %T", priv)) - } - // encrypt private key using passphrase - privArmor := mintkey.EncryptArmorPrivKey(privkey, passphrase) - // make Info - pub := privkey.PubKey() - pubkey, ok := pub.(emintCrypto.PubKeySecp256k1) - if !ok { - panic(fmt.Sprintf("invalid public key type: %T", pub)) - } - info := newLocalInfo(name, pubkey, privArmor) - kb.writeInfo(name, info) - return info -} - -func (kb dbKeybase) writeLedgerKey(name string, pub tmcrypto.PubKey, path hd.BIP44Params) cosmosKeys.Info { - pubkey, ok := pub.(emintCrypto.PubKeySecp256k1) - if !ok { - panic(fmt.Sprintf("invalid public key type: %T", pub)) - } - info := newLedgerInfo(name, pubkey, path) - kb.writeInfo(name, info) - return info -} - -func (kb dbKeybase) writeOfflineKey(name string, pub tmcrypto.PubKey) cosmosKeys.Info { - pubkey, ok := pub.(emintCrypto.PubKeySecp256k1) - if !ok { - panic(fmt.Sprintf("invalid public key type: %T", pub)) - } - info := newOfflineInfo(name, pubkey) - kb.writeInfo(name, info) - return info -} - -func (kb dbKeybase) writeInfo(name string, info cosmosKeys.Info) { - // write the info by key - key := infoKey(name) - serializedInfo := writeInfo(info) - kb.db.SetSync(key, serializedInfo) - // store a pointer to the infokey by address for fast lookup - kb.db.SetSync(addrKey(info.GetAddress()), key) -} - -func addrKey(address types.AccAddress) []byte { - return []byte(fmt.Sprintf("%s.%s", address.String(), addressSuffix)) -} - -func infoKey(name string) []byte { - return []byte(fmt.Sprintf("%s.%s", name, infoSuffix)) -} diff --git a/crypto/keys/keys.go b/crypto/keys/keys.go deleted file mode 100644 index 72c14ca1..00000000 --- a/crypto/keys/keys.go +++ /dev/null @@ -1,13 +0,0 @@ -package keys - -import ( - cosmosKeys "github.com/cosmos/cosmos-sdk/crypto/keys" -) - -// SigningAlgo defines an algorithm to derive key-pairs which can be used for cryptographic signing. -type SigningAlgo string - -const ( - // Secp256k1 uses the Bitcoin secp256k1 ECDSA parameters. - Secp256k1 = cosmosKeys.SigningAlgo("emintsecp256k1") -) diff --git a/crypto/keys/lazy_keybase.go b/crypto/keys/lazy_keybase.go deleted file mode 100644 index a38805b6..00000000 --- a/crypto/keys/lazy_keybase.go +++ /dev/null @@ -1,222 +0,0 @@ -package keys - -import ( - "fmt" - - "github.com/tendermint/tendermint/crypto" - cmn "github.com/tendermint/tendermint/libs/common" - - cosmosKeys "github.com/cosmos/cosmos-sdk/crypto/keys" - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -var _ cosmosKeys.Keybase = lazyKeybase{} - -type lazyKeybase struct { - name string - dir string -} - -// New creates a new instance of a lazy keybase. -func New(name, dir string) cosmosKeys.Keybase { - if err := cmn.EnsureDir(dir, 0700); err != nil { - panic(fmt.Sprintf("failed to create Keybase directory: %s", err)) - } - - return lazyKeybase{name: name, dir: dir} -} - -func (lkb lazyKeybase) List() ([]cosmosKeys.Info, error) { - db, err := sdk.NewLevelDB(lkb.name, lkb.dir) - if err != nil { - return nil, err - } - defer db.Close() - - return newDbKeybase(db).List() -} - -func (lkb lazyKeybase) Get(name string) (cosmosKeys.Info, error) { - db, err := sdk.NewLevelDB(lkb.name, lkb.dir) - if err != nil { - return nil, err - } - defer db.Close() - - return newDbKeybase(db).Get(name) -} - -func (lkb lazyKeybase) GetByAddress(address sdk.AccAddress) (cosmosKeys.Info, error) { - db, err := sdk.NewLevelDB(lkb.name, lkb.dir) - if err != nil { - return nil, err - } - defer db.Close() - - return newDbKeybase(db).GetByAddress(address) -} - -func (lkb lazyKeybase) Delete(name, passphrase string, skipPass bool) error { - db, err := sdk.NewLevelDB(lkb.name, lkb.dir) - if err != nil { - return err - } - defer db.Close() - - return newDbKeybase(db).Delete(name, passphrase, skipPass) -} - -func (lkb lazyKeybase) Sign(name, passphrase string, msg []byte) ([]byte, crypto.PubKey, error) { - db, err := sdk.NewLevelDB(lkb.name, lkb.dir) - if err != nil { - return nil, nil, err - } - defer db.Close() - - return newDbKeybase(db).Sign(name, passphrase, msg) -} - -func (lkb lazyKeybase) CreateMnemonic(name string, language cosmosKeys.Language, passwd string, algo cosmosKeys.SigningAlgo) (info cosmosKeys.Info, seed string, err error) { - db, err := sdk.NewLevelDB(lkb.name, lkb.dir) - if err != nil { - return nil, "", err - } - defer db.Close() - - return newDbKeybase(db).CreateMnemonic(name, language, passwd, algo) -} - -func (lkb lazyKeybase) CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd string, account uint32, index uint32) (cosmosKeys.Info, error) { - db, err := sdk.NewLevelDB(lkb.name, lkb.dir) - if err != nil { - return nil, err - } - defer db.Close() - - return newDbKeybase(db).CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd, account, index) -} - -func (lkb lazyKeybase) Derive(name, mnemonic, bip39Passwd, encryptPasswd string, params hd.BIP44Params) (cosmosKeys.Info, error) { - db, err := sdk.NewLevelDB(lkb.name, lkb.dir) - if err != nil { - return nil, err - } - defer db.Close() - - return newDbKeybase(db).Derive(name, mnemonic, bip39Passwd, encryptPasswd, params) -} - -func (lkb lazyKeybase) CreateLedger(name string, algo cosmosKeys.SigningAlgo, hrp string, account, index uint32) (info cosmosKeys.Info, err error) { - db, err := sdk.NewLevelDB(lkb.name, lkb.dir) - if err != nil { - return nil, err - } - defer db.Close() - - return newDbKeybase(db).CreateLedger(name, algo, hrp, account, index) -} - -func (lkb lazyKeybase) CreateOffline(name string, pubkey crypto.PubKey) (info cosmosKeys.Info, err error) { - db, err := sdk.NewLevelDB(lkb.name, lkb.dir) - if err != nil { - return nil, err - } - defer db.Close() - - return newDbKeybase(db).CreateOffline(name, pubkey) -} - -func (lkb lazyKeybase) CreateMulti(name string, pubkey crypto.PubKey) (info cosmosKeys.Info, err error) { - db, err := sdk.NewLevelDB(lkb.name, lkb.dir) - if err != nil { - return nil, err - } - defer db.Close() - - return newDbKeybase(db).CreateMulti(name, pubkey) -} - -func (lkb lazyKeybase) Update(name, oldpass string, getNewpass func() (string, error)) error { - db, err := sdk.NewLevelDB(lkb.name, lkb.dir) - if err != nil { - return err - } - defer db.Close() - - return newDbKeybase(db).Update(name, oldpass, getNewpass) -} - -func (lkb lazyKeybase) Import(name string, armor string) (err error) { - db, err := sdk.NewLevelDB(lkb.name, lkb.dir) - if err != nil { - return err - } - defer db.Close() - - return newDbKeybase(db).Import(name, armor) -} - -func (lkb lazyKeybase) ImportPrivKey(name string, armor string, passphrase string) error { - db, err := sdk.NewLevelDB(lkb.name, lkb.dir) - if err != nil { - return err - } - defer db.Close() - - return newDbKeybase(db).ImportPrivKey(name, armor, passphrase) -} - -func (lkb lazyKeybase) ImportPubKey(name string, armor string) (err error) { - db, err := sdk.NewLevelDB(lkb.name, lkb.dir) - if err != nil { - return err - } - defer db.Close() - - return newDbKeybase(db).ImportPubKey(name, armor) -} - -func (lkb lazyKeybase) Export(name string) (armor string, err error) { - db, err := sdk.NewLevelDB(lkb.name, lkb.dir) - if err != nil { - return "", err - } - defer db.Close() - - return newDbKeybase(db).Export(name) -} - -func (lkb lazyKeybase) ExportPubKey(name string) (armor string, err error) { - db, err := sdk.NewLevelDB(lkb.name, lkb.dir) - if err != nil { - return "", err - } - defer db.Close() - - return newDbKeybase(db).ExportPubKey(name) -} - -func (lkb lazyKeybase) ExportPrivateKeyObject(name string, passphrase string) (crypto.PrivKey, error) { - db, err := sdk.NewLevelDB(lkb.name, lkb.dir) - if err != nil { - return nil, err - } - defer db.Close() - - return newDbKeybase(db).ExportPrivateKeyObject(name, passphrase) -} - -func (lkb lazyKeybase) ExportPrivKey(name string, decryptPassphrase string, - encryptPassphrase string) (armor string, err error) { - - db, err := sdk.NewLevelDB(lkb.name, lkb.dir) - if err != nil { - return "", err - } - defer db.Close() - - return newDbKeybase(db).ExportPrivKey(name, decryptPassphrase, encryptPassphrase) -} - -func (lkb lazyKeybase) CloseDB() {} diff --git a/crypto/keys/output.go b/crypto/keys/output.go deleted file mode 100644 index cd255bd2..00000000 --- a/crypto/keys/output.go +++ /dev/null @@ -1,111 +0,0 @@ -package keys - -import ( - "encoding/hex" - - sdk "github.com/cosmos/cosmos-sdk/types" - - cosmosKeys "github.com/cosmos/cosmos-sdk/crypto/keys" -) - -// KeyOutput defines a structure wrapping around an Info object used for output -// functionality. -type KeyOutput struct { - Name string `json:"name"` - Type string `json:"type"` - Address string `json:"address"` - ETHAddress string `json:"ethaddress"` - PubKey string `json:"pubkey"` - ETHPubKey string `json:"ethpubkey"` - Mnemonic string `json:"mnemonic,omitempty"` - Threshold uint `json:"threshold,omitempty"` -} - -// NewKeyOutput creates a default KeyOutput instance without Mnemonic, Threshold and PubKeys -func NewKeyOutput(name, keyType, address, ethaddress, pubkey, ethpubkey string) KeyOutput { - return KeyOutput{ - Name: name, - Type: keyType, - Address: address, - ETHAddress: ethaddress, - PubKey: pubkey, - ETHPubKey: ethpubkey, - } -} - -// Bech32KeysOutput returns a slice of KeyOutput objects, each with the "acc" -// Bech32 prefixes, given a slice of Info objects. It returns an error if any -// call to Bech32KeyOutput fails. -func Bech32KeysOutput(infos []cosmosKeys.Info) ([]KeyOutput, error) { - kos := make([]KeyOutput, len(infos)) - for i, info := range infos { - ko, err := Bech32KeyOutput(info) - if err != nil { - return nil, err - } - kos[i] = ko - } - - return kos, nil -} - -// Bech32ConsKeyOutput create a KeyOutput in with "cons" Bech32 prefixes. -func Bech32ConsKeyOutput(keyInfo cosmosKeys.Info) (KeyOutput, error) { - address := keyInfo.GetPubKey().Address() - - bechPubKey, err := sdk.Bech32ifyConsPub(keyInfo.GetPubKey()) - if err != nil { - return KeyOutput{}, err - } - - return NewKeyOutput( - keyInfo.GetName(), - keyInfo.GetType().String(), - sdk.ConsAddress(address.Bytes()).String(), - getEthAddress(keyInfo), - bechPubKey, - hex.EncodeToString(keyInfo.GetPubKey().Bytes()), - ), nil -} - -// Bech32ValKeyOutput create a KeyOutput in with "val" Bech32 prefixes. -func Bech32ValKeyOutput(keyInfo cosmosKeys.Info) (KeyOutput, error) { - address := keyInfo.GetPubKey().Address() - - bechPubKey, err := sdk.Bech32ifyValPub(keyInfo.GetPubKey()) - if err != nil { - return KeyOutput{}, err - } - - return NewKeyOutput( - keyInfo.GetName(), - keyInfo.GetType().String(), - sdk.ValAddress(address.Bytes()).String(), - getEthAddress(keyInfo), - bechPubKey, - hex.EncodeToString(keyInfo.GetPubKey().Bytes()), - ), nil -} - -// Bech32KeyOutput create a KeyOutput in with "acc" Bech32 prefixes. -func Bech32KeyOutput(keyInfo cosmosKeys.Info) (KeyOutput, error) { - address := keyInfo.GetPubKey().Address() - - bechPubKey, err := sdk.Bech32ifyAccPub(keyInfo.GetPubKey()) - if err != nil { - return KeyOutput{}, err - } - - return NewKeyOutput( - keyInfo.GetName(), - keyInfo.GetType().String(), - sdk.AccAddress(address.Bytes()).String(), - getEthAddress(keyInfo), - bechPubKey, - hex.EncodeToString(keyInfo.GetPubKey().Bytes()), - ), nil -} - -func getEthAddress(info cosmosKeys.Info) string { - return info.GetPubKey().Address().String() -} diff --git a/crypto/keys/types.go b/crypto/keys/types.go deleted file mode 100644 index 69fc63b1..00000000 --- a/crypto/keys/types.go +++ /dev/null @@ -1,156 +0,0 @@ -package keys - -import ( - "fmt" - - cosmosKeys "github.com/cosmos/cosmos-sdk/crypto/keys" - emintCrypto "github.com/cosmos/ethermint/crypto" - "github.com/tendermint/tendermint/crypto" - - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" - "github.com/cosmos/cosmos-sdk/types" -) - -// KeyType reflects a human-readable type for key listing. -type KeyType uint - -// Info KeyTypes -const ( - TypeLocal KeyType = 0 - TypeLedger KeyType = 1 - TypeOffline KeyType = 2 - TypeMulti KeyType = 3 -) - -var keyTypes = map[KeyType]string{ - TypeLocal: "local", - TypeLedger: "ledger", - TypeOffline: "offline", - TypeMulti: "multi", -} - -// String implements the stringer interface for KeyType. -func (kt KeyType) String() string { - return keyTypes[kt] -} - -var ( - _ cosmosKeys.Info = &localInfo{} - _ cosmosKeys.Info = &ledgerInfo{} - _ cosmosKeys.Info = &offlineInfo{} -) - -// localInfo is the public information about a locally stored key -type localInfo struct { - Name string `json:"name"` - PubKey emintCrypto.PubKeySecp256k1 `json:"pubkey"` - PrivKeyArmor string `json:"privkey.armor"` -} - -func newLocalInfo(name string, pub emintCrypto.PubKeySecp256k1, privArmor string) cosmosKeys.Info { - return &localInfo{ - Name: name, - PubKey: pub, - PrivKeyArmor: privArmor, - } -} - -func (i localInfo) GetType() cosmosKeys.KeyType { - return cosmosKeys.TypeLocal -} - -func (i localInfo) GetName() string { - return i.Name -} - -func (i localInfo) GetPubKey() crypto.PubKey { - return i.PubKey -} - -func (i localInfo) GetAddress() types.AccAddress { - return i.PubKey.Address().Bytes() -} - -func (i localInfo) GetPath() (*hd.BIP44Params, error) { - return nil, fmt.Errorf("BIP44 Paths are not available for this type") -} - -// ledgerInfo is the public information about a Ledger key -type ledgerInfo struct { - Name string `json:"name"` - PubKey emintCrypto.PubKeySecp256k1 `json:"pubkey"` - Path hd.BIP44Params `json:"path"` -} - -func newLedgerInfo(name string, pub emintCrypto.PubKeySecp256k1, path hd.BIP44Params) cosmosKeys.Info { - return &ledgerInfo{ - Name: name, - PubKey: pub, - Path: path, - } -} - -func (i ledgerInfo) GetType() cosmosKeys.KeyType { - return cosmosKeys.TypeLedger -} - -func (i ledgerInfo) GetName() string { - return i.Name -} - -func (i ledgerInfo) GetPubKey() crypto.PubKey { - return i.PubKey -} - -func (i ledgerInfo) GetAddress() types.AccAddress { - return i.PubKey.Address().Bytes() -} - -func (i ledgerInfo) GetPath() (*hd.BIP44Params, error) { - tmp := i.Path - return &tmp, nil -} - -// offlineInfo is the public information about an offline key -type offlineInfo struct { - Name string `json:"name"` - PubKey emintCrypto.PubKeySecp256k1 `json:"pubkey"` -} - -func newOfflineInfo(name string, pub emintCrypto.PubKeySecp256k1) cosmosKeys.Info { - return &offlineInfo{ - Name: name, - PubKey: pub, - } -} - -func (i offlineInfo) GetType() cosmosKeys.KeyType { - return cosmosKeys.TypeOffline -} - -func (i offlineInfo) GetName() string { - return i.Name -} - -func (i offlineInfo) GetPubKey() crypto.PubKey { - return i.PubKey -} - -func (i offlineInfo) GetAddress() types.AccAddress { - return i.PubKey.Address().Bytes() -} - -func (i offlineInfo) GetPath() (*hd.BIP44Params, error) { - return nil, fmt.Errorf("BIP44 Paths are not available for this type") -} - -// encoding info -func writeInfo(i cosmosKeys.Info) []byte { - return cdc.MustMarshalBinaryLengthPrefixed(i) -} - -// decoding info -func readInfo(bz []byte) (info cosmosKeys.Info, err error) { - err = cdc.UnmarshalBinaryLengthPrefixed(bz, &info) - return -} diff --git a/crypto/keys/types_test.go b/crypto/keys/types_test.go deleted file mode 100644 index f4e9cfba..00000000 --- a/crypto/keys/types_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package keys - -import ( - "testing" - - "github.com/cosmos/cosmos-sdk/crypto/keys/hd" - "github.com/cosmos/ethermint/crypto" - "github.com/stretchr/testify/assert" -) - -func TestWriteReadInfo(t *testing.T) { - tmpKey, err := crypto.GenerateKey() - assert.NoError(t, err) - pkey := tmpKey.PubKey() - pubkey, ok := pkey.(crypto.PubKeySecp256k1) - assert.True(t, ok) - - info := newOfflineInfo("offline", pubkey) - bytes := writeInfo(info) - assert.NotNil(t, bytes) - - regeneratedKey, err := readInfo(bytes) - assert.NoError(t, err) - assert.Equal(t, info.GetPubKey(), regeneratedKey.GetPubKey()) - assert.Equal(t, info.GetName(), regeneratedKey.GetName()) - - info = newLocalInfo("local", pubkey, "testarmor") - bytes = writeInfo(info) - assert.NotNil(t, bytes) - - regeneratedKey, err = readInfo(bytes) - assert.NoError(t, err) - assert.Equal(t, info.GetPubKey(), regeneratedKey.GetPubKey()) - assert.Equal(t, info.GetName(), regeneratedKey.GetName()) - - info = newLedgerInfo("ledger", pubkey, - hd.BIP44Params{Purpose: 1, CoinType: 1, Account: 1, Change: false, AddressIndex: 1}) - bytes = writeInfo(info) - assert.NotNil(t, bytes) - - regeneratedKey, err = readInfo(bytes) - assert.NoError(t, err) - assert.Equal(t, info.GetPubKey(), regeneratedKey.GetPubKey()) - assert.Equal(t, info.GetName(), regeneratedKey.GetName()) - -} diff --git a/crypto/secp256k1.go b/crypto/secp256k1.go index 0470b2b4..7b6c4cdb 100644 --- a/crypto/secp256k1.go +++ b/crypto/secp256k1.go @@ -7,9 +7,19 @@ import ( ethcrypto "github.com/ethereum/go-ethereum/crypto" ethsecp256k1 "github.com/ethereum/go-ethereum/crypto/secp256k1" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + tmcrypto "github.com/tendermint/tendermint/crypto" + tmamino "github.com/tendermint/tendermint/crypto/encoding/amino" ) +func init() { + tmamino.RegisterKeyType(PubKeySecp256k1{}, PubKeyAminoName) + tmamino.RegisterKeyType(PrivKeySecp256k1{}, PrivKeyAminoName) + authtypes.RegisterAccountTypeCodec(PubKeySecp256k1{}, PubKeyAminoName) + authtypes.RegisterAccountTypeCodec(PrivKeySecp256k1{}, PrivKeyAminoName) +} + // ---------------------------------------------------------------------------- // secp256k1 Private Key diff --git a/go.mod b/go.mod index 0762dc1a..301c4fe8 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8 // indirect github.com/cespare/cp v1.1.1 // indirect github.com/cosmos/cosmos-sdk v0.34.4-0.20191031200835-02c6c9fafd58 - github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d + github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d // indirect github.com/deckarep/golang-set v1.7.1 // indirect github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712 // indirect github.com/elastic/gosigar v0.10.3 // indirect @@ -35,8 +35,7 @@ require ( github.com/rjeczalik/notify v0.9.2 // indirect github.com/spf13/afero v1.2.2 // indirect github.com/spf13/cobra v0.0.5 - github.com/spf13/pflag v1.0.5 - github.com/spf13/viper v1.4.0 + github.com/spf13/viper v1.5.0 github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48 // indirect github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect @@ -54,8 +53,10 @@ require ( google.golang.org/genproto v0.0.0-20190708153700-3bdd9d9f5532 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect - gopkg.in/urfave/cli.v1 v1.0.0-00010101000000-000000000000 // indirect - gopkg.in/yaml.v2 v2.2.4 + gopkg.in/urfave/cli.v1 v1.20.0 // indirect ) -replace gopkg.in/urfave/cli.v1 => github.com/urfave/cli v1.21.0 +replace ( + github.com/cosmos/cosmos-sdk v0.34.4-0.20191031200835-02c6c9fafd58 => github.com/chainsafe/cosmos-sdk v0.34.4-0.20191105182341-b5e2a1dfdcf6 + github.com/tendermint/tendermint v0.32.7 => github.com/chainsafe/tendermint v0.32.2-0.20191105211315-bd56da568e15 +) diff --git a/go.sum b/go.sum index 64445c20..799439ea 100644 --- a/go.sum +++ b/go.sum @@ -40,6 +40,10 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/chainsafe/cosmos-sdk v0.34.4-0.20191105182341-b5e2a1dfdcf6 h1:v3aiYKq2JKNp86QHW53GuyIljwnOm+zF4H9WoQwqir0= +github.com/chainsafe/cosmos-sdk v0.34.4-0.20191105182341-b5e2a1dfdcf6/go.mod h1:jfj68M7UAsSvG+XmGU5zVfSij5fzlOdiQc1NKt+YK2A= +github.com/chainsafe/tendermint v0.32.2-0.20191105211315-bd56da568e15 h1:wGxBiAN4kWM/XfQnOIcnQH6rdzwfMelph+Y5CjqzYcw= +github.com/chainsafe/tendermint v0.32.2-0.20191105211315-bd56da568e15/go.mod h1:zhk6jGOCB5pi7NF8XtP77lqcDZ5n0biPwl2/AyS/vPM= github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -48,8 +52,6 @@ github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8Nz github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cosmos/cosmos-sdk v0.34.4-0.20191031200835-02c6c9fafd58 h1:B3fXc6Y9ztj9glE2ANU0+NQJ0M1BXaG5LpnyKFwHW4M= -github.com/cosmos/cosmos-sdk v0.34.4-0.20191031200835-02c6c9fafd58/go.mod h1:PuN72vbZxlorpnHmoIl6RjzVMXEOMejmwORJlZ74K7Q= github.com/cosmos/go-bip39 v0.0.0-20180618194314-52158e4697b8 h1:Iwin12wRQtyZhH6FV3ykFcdGNlYEzoeR0jN8Vn+JWsI= github.com/cosmos/go-bip39 v0.0.0-20180618194314-52158e4697b8/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d h1:49RLWk1j44Xu4fjHb6JFYmeUnDORVwHNkDxaQ0ctCVU= @@ -115,8 +117,6 @@ github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= @@ -308,8 +308,8 @@ github.com/spf13/viper v1.0.0 h1:RUA/ghS2i64rlnn4ydTfblY8Og8QzcPtCcHvgMn+w/I= github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.5.0 h1:GpsTwfsQ27oS/Aha/6d1oD7tpKIqWnOA6tgOX9HHkt4= +github.com/spf13/viper v1.5.0/go.mod h1:AkYRkVJF8TkSG/xet6PzXX+l39KhhXa2pdqVSxnTcn4= github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48 h1:ju5UTwk5Odtm4trrY+4Ca4RMj5OyXbmVeDAVad2T0Jw= github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE= @@ -328,6 +328,8 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stumble/gorocksdb v0.0.3 h1:9UU+QA1pqFYJuf9+5p7z1IqdE5k0mma4UAeu2wmX8kA= github.com/stumble/gorocksdb v0.0.3/go.mod h1:v6IHdFBXk5DJ1K4FZ0xi+eY737quiiBxYtSWXadLybY= +github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965 h1:1oFLiOyVl+W7bnBzGhf7BbIv9loSFQcieWWYIjLqcAw= github.com/syndtr/goleveldb v1.0.1-0.20190318030020-c3a204f8e965/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s= @@ -341,8 +343,6 @@ github.com/tendermint/go-amino v0.15.1/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoM github.com/tendermint/iavl v0.12.4 h1:hd1woxUGISKkfUWBA4mmmTwOua6PQZTJM/F0FDrmMV8= github.com/tendermint/iavl v0.12.4/go.mod h1:8LHakzt8/0G3/I8FUU0ReNx98S/EP6eyPJkAUvEXT/o= github.com/tendermint/tendermint v0.32.1/go.mod h1:jmPDAKuNkev9793/ivn/fTBnfpA9mGBww8MPRNPNxnU= -github.com/tendermint/tendermint v0.32.7 h1:Szu5Fm1L3pvn3t4uQxPAcP+7ndZEQKgLie/yokM56rU= -github.com/tendermint/tendermint v0.32.7/go.mod h1:D2+A3pNjY+Po72X0mTfaXorFhiVI8dh/Zg640FGyGtE= github.com/tendermint/tm-db v0.1.1 h1:G3Xezy3sOk9+ekhjZ/kjArYIs1SmwV+1OUgNkj7RgV0= github.com/tendermint/tm-db v0.1.1/go.mod h1:0cPKWu2Mou3IlxecH+MEUSYc1Ch537alLe6CpFrKzgw= github.com/tendermint/tm-db v0.2.0 h1:rJxgdqn6fIiVJZy4zLpY1qVlyD0TU6vhkT4kEf71TQQ= @@ -352,8 +352,6 @@ github.com/tyler-smith/go-bip39 v1.0.0 h1:FOHg9gaQLeBBRbHE/QrTLfEiBHy5pQ/yXzf9JG github.com/tyler-smith/go-bip39 v1.0.0/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/urfave/cli v1.21.0 h1:wYSSj06510qPIzGSua9ZqsncMmWE3Zr55KBERygyrxE= -github.com/urfave/cli v1.21.0/go.mod h1:lxDj6qX9Q6lWQxIrbrT0nwecwUtRnhVZAJjJZrVUZZQ= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= @@ -414,6 +412,7 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -447,8 +446,8 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.0 h1:J0UbZOIrCAl+fpTOf8YLs4dJo8L/owV4LYVtAXQoPkw= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1 h1:q4XQuHFC6I28BKZpo6IYyb3mNO+l7lSOxRuYTCiDfXk= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -463,6 +462,8 @@ gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHN gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= +gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/keys/add.go b/keys/add.go deleted file mode 100644 index aebf1d13..00000000 --- a/keys/add.go +++ /dev/null @@ -1,258 +0,0 @@ -package keys - -import ( - "bufio" - "errors" - "fmt" - - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/client/input" - clientkeys "github.com/cosmos/cosmos-sdk/client/keys" - cosmosKeys "github.com/cosmos/cosmos-sdk/crypto/keys" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/ethermint/crypto/keys" - - "github.com/spf13/cobra" - "github.com/spf13/viper" - - "github.com/cosmos/go-bip39" - - "github.com/tendermint/tendermint/libs/cli" -) - -const ( - flagInteractive = "interactive" - flagRecover = "recover" - flagNoBackup = "no-backup" - // flagDryRun = "dry-run" - flagAccount = "account" - flagIndex = "index" - // flagNoSort = "nosort" - - // DefaultKeyPass contains the default key password for genesis transactions - DefaultKeyPass = "12345678" - - mnemonicEntropySize = 256 -) - -func addKeyCommand() *cobra.Command { - cmd := &cobra.Command{ - Use: "add ", - Short: "Add an encrypted private key (either newly generated or recovered), encrypt it, and save to disk", - Long: `Derive a new private key and encrypt to disk. -Optionally specify a BIP39 mnemonic, a BIP39 passphrase to further secure the mnemonic, -and a bip32 HD path to derive a specific account. The key will be stored under the given name -and encrypted with the given password. The only input that is required is the encryption password. - -If run with -i, it will prompt the user for BIP44 path, BIP39 mnemonic, and passphrase. -The flag --recover allows one to recover a key from a seed passphrase. -If run with --dry-run, a key would be generated (or recovered) but not stored to the -local keystore. -Use the --pubkey flag to add arbitrary public keys to the keystore for constructing -multisig transactions. -`, - Args: cobra.ExactArgs(1), - RunE: runAddCmd, - } - // cmd.Flags().StringSlice(flagMultisig, nil, "Construct and store a multisig public key (implies --pubkey)") - // cmd.Flags().Uint(flagMultiSigThreshold, 1, "K out of N required signatures. For use in conjunction with --multisig") - // cmd.Flags().Bool(flagNoSort, false, "Keys passed to --multisig are taken in the order they're supplied") - cmd.Flags().String(FlagPublicKey, "", "Parse a public key in bech32 format and save it to disk") - cmd.Flags().BoolP(flagInteractive, "i", false, "Interactively prompt user for BIP39 passphrase and mnemonic") - // cmd.Flags().Bool(flags.FlagUseLedger, false, "Store a local reference to a private key on a Ledger device") - cmd.Flags().Bool(flagRecover, false, "Provide seed phrase to recover existing key instead of creating") - cmd.Flags().Bool(flagNoBackup, false, "Don't print out seed phrase (if others are watching the terminal)") - // cmd.Flags().Bool(flagDryRun, false, "Perform action, but don't add key to local keystore") - 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") - return cmd -} - -/* -input -- bip39 mnemonic -- bip39 passphrase -- bip44 path -- local encryption password -output -- armor encrypted private key (saved to file) -*/ -func runAddCmd(cmd *cobra.Command, args []string) error { - var kb cosmosKeys.Keybase - var err error - var encryptPassword string - - inBuf := bufio.NewReader(cmd.InOrStdin()) - name := args[0] - - interactive := viper.GetBool(flagInteractive) - showMnemonic := !viper.GetBool(flagNoBackup) - - kb, err = NewKeyBaseFromHomeFlag() - if err != nil { - return err - } - - _, err = kb.Get(name) - if err == nil { - // account exists, ask for user confirmation - response, err2 := input.GetConfirmation(fmt.Sprintf("override the existing name %s", name), inBuf) - if err2 != nil { - return err2 - } - if !response { - return errors.New("aborted") - } - } - - // ask for a password when generating a local key - if viper.GetString(FlagPublicKey) == "" && !viper.GetBool(flags.FlagUseLedger) { - encryptPassword, err = input.GetCheckPassword( - "Enter a passphrase to encrypt your key to disk:", - "Repeat the passphrase:", inBuf) - if err != nil { - return err - } - } - // } - - if viper.GetString(FlagPublicKey) != "" { - pk, err := sdk.GetAccPubKeyBech32(viper.GetString(FlagPublicKey)) - if err != nil { - return err - } - _, err = kb.CreateOffline(name, pk) - if err != nil { - return err - } - return nil - } - - account := uint32(viper.GetInt(flagAccount)) - index := uint32(viper.GetInt(flagIndex)) - - // // If we're using ledger, only thing we need is the path and the bech32 prefix. - // if viper.GetBool(flags.FlagUseLedger) { - // bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix() - // info, err := kb.CreateLedger(name, keys.Secp256k1, bech32PrefixAccAddr, account, index) - // if err != nil { - // return err - // } - - // return printCreate(cmd, info, false, "") - // } - - // Get bip39 mnemonic - var mnemonic string - var bip39Passphrase string - - if interactive || viper.GetBool(flagRecover) { - bip39Message := "Enter your bip39 mnemonic" - if !viper.GetBool(flagRecover) { - bip39Message = "Enter your bip39 mnemonic, or hit enter to generate one." - } - - mnemonic, err = input.GetString(bip39Message, inBuf) - if err != nil { - return err - } - - if !bip39.IsMnemonicValid(mnemonic) { - return errors.New("invalid mnemonic") - } - } - - if len(mnemonic) == 0 { - // read entropy seed straight from crypto.Rand and convert to mnemonic - entropySeed, err := bip39.NewEntropy(mnemonicEntropySize) - if err != nil { - return err - } - - mnemonic, err = bip39.NewMnemonic(entropySeed[:]) - if err != nil { - return err - } - } - - // override bip39 passphrase - if interactive { - bip39Passphrase, err = input.GetString( - "Enter your bip39 passphrase. This is combined with the mnemonic to derive the seed. "+ - "Most users should just hit enter to use the default, \"\"", inBuf) - if err != nil { - return err - } - - // if they use one, make them re-enter it - if len(bip39Passphrase) != 0 { - p2, err := input.GetString("Repeat the passphrase:", inBuf) - if err != nil { - return err - } - - if bip39Passphrase != p2 { - return errors.New("passphrases don't match") - } - } - } - - info, err := kb.CreateAccount(name, mnemonic, bip39Passphrase, encryptPassword, account, index) - if err != nil { - return err - } - - // Recover key from seed passphrase - if viper.GetBool(flagRecover) { - // Hide mnemonic from output - showMnemonic = false - mnemonic = "" - } - - return printCreate(cmd, info, showMnemonic, mnemonic) -} - -func printCreate(cmd *cobra.Command, info cosmosKeys.Info, showMnemonic bool, mnemonic string) error { - output := viper.Get(cli.OutputFlag) - - switch output { - case clientkeys.OutputFormatText: - cmd.PrintErrln() - printKeyInfo(info, keys.Bech32KeyOutput) - - // print mnemonic unless requested not to. - if showMnemonic { - cmd.PrintErrln("\n**Important** write this mnemonic phrase in a safe place.") - cmd.PrintErrln("It is the only way to recover your account if you ever forget your password.") - cmd.PrintErrln("") - cmd.PrintErrln(mnemonic) - } - case clientkeys.OutputFormatJSON: - out, err := keys.Bech32KeyOutput(info) - if err != nil { - return err - } - - if showMnemonic { - out.Mnemonic = mnemonic - } - - var jsonString []byte - if viper.GetBool(flags.FlagIndentResponse) { - jsonString, err = cdc.MarshalJSONIndent(out, "", " ") - } else { - jsonString, err = cdc.MarshalJSON(out) - } - - if err != nil { - return err - } - cmd.PrintErrln(string(jsonString)) - default: - return fmt.Errorf("I can't speak: %s", output) - } - - return nil -} diff --git a/keys/add_test.go b/keys/add_test.go deleted file mode 100644 index e158cf04..00000000 --- a/keys/add_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package keys - -import ( - "testing" - - "github.com/spf13/viper" - "github.com/stretchr/testify/assert" - - "github.com/tendermint/tendermint/libs/cli" - - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/tests" -) - -func TestAddCommandBasic(t *testing.T) { - cmd := addKeyCommand() - assert.NotNil(t, cmd) - mockIn, _, _ := tests.ApplyMockIO(cmd) - - kbHome, kbCleanUp := tests.NewTestCaseDir(t) - assert.NotNil(t, kbHome) - defer kbCleanUp() - viper.Set(flags.FlagHome, kbHome) - - viper.Set(cli.OutputFlag, OutputFormatText) - - mockIn.Reset("test1234\ntest1234\n") - err := runAddCmd(cmd, []string{"keyname1"}) - assert.NoError(t, err) - - viper.Set(cli.OutputFlag, OutputFormatText) - - mockIn.Reset("test1234\ntest1234\n") - err = runAddCmd(cmd, []string{"keyname1"}) - assert.Error(t, err) - - viper.Set(cli.OutputFlag, OutputFormatText) - - mockIn.Reset("y\ntest1234\ntest1234\n") - err = runAddCmd(cmd, []string{"keyname1"}) - assert.NoError(t, err) - - viper.Set(cli.OutputFlag, OutputFormatJSON) - - mockIn.Reset("test1234\ntest1234\n") - err = runAddCmd(cmd, []string{"keyname2"}) - assert.NoError(t, err) -} diff --git a/keys/codec.go b/keys/codec.go deleted file mode 100644 index eae45446..00000000 --- a/keys/codec.go +++ /dev/null @@ -1,23 +0,0 @@ -package keys - -import ( - "github.com/cosmos/cosmos-sdk/codec" -) - -var cdc *codec.Codec - -func init() { - cdc = codec.New() - codec.RegisterCrypto(cdc) - cdc.Seal() -} - -// marshal keys -func MarshalJSON(o interface{}) ([]byte, error) { - return cdc.MarshalJSON(o) -} - -// unmarshal json -func UnmarshalJSON(bz []byte, ptr interface{}) error { - return cdc.UnmarshalJSON(bz, ptr) -} diff --git a/keys/root.go b/keys/root.go deleted file mode 100644 index 1fc55ea6..00000000 --- a/keys/root.go +++ /dev/null @@ -1,34 +0,0 @@ -package keys - -import ( - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/client/flags" -) - -// Commands registers a sub-tree of commands to interact with -// local private key storage. -func Commands() *cobra.Command { - cmd := &cobra.Command{ - Use: "emintkeys", - Short: "Add or view local private keys", - Long: `Keys allows you to manage your local keystore for tendermint. - - These keys may be in any format supported by go-crypto and can be - used by light-clients, full nodes, or any other application that - needs to sign with a private key.`, - } - cmd.AddCommand( - // mnemonicKeyCommand(), - addKeyCommand(), - // exportKeyCommand(), - // importKeyCommand(), - // listKeysCmd(), - showKeysCmd(), - flags.LineBreak, - // deleteKeyCommand(), - // updateKeyCommand(), - // parseKeyStringCommand(), - ) - return cmd -} diff --git a/keys/show.go b/keys/show.go deleted file mode 100644 index bd2f8065..00000000 --- a/keys/show.go +++ /dev/null @@ -1,132 +0,0 @@ -package keys - -import ( - "errors" - "fmt" - - "github.com/spf13/cobra" - "github.com/spf13/viper" - - "github.com/tendermint/tendermint/libs/cli" - - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/crypto" - cosmosKeys "github.com/cosmos/cosmos-sdk/crypto/keys" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/ethermint/crypto/keys" -) - -const ( - // FlagAddress is the flag for the user's address on the command line. - FlagAddress = "address" - // FlagAddress is the flag for the user's address on the command line. - FlagETHAddress = "ethwallet" - // FlagPublicKey represents the user's public key on the command line. - FlagPublicKey = "pubkey" - // FlagBechPrefix defines a desired Bech32 prefix encoding for a key. - FlagBechPrefix = "bech" - // FlagDevice indicates that the information should be shown in the device - FlagDevice = "device" -) - -func showKeysCmd() *cobra.Command { - cmd := &cobra.Command{ - Use: "show ", - Short: "Show key info for the given name", - Long: `Return public details of a single local key.`, - Args: cobra.MinimumNArgs(1), - RunE: runShowCmd, - } - - cmd.Flags().String(FlagBechPrefix, sdk.PrefixAccount, "The Bech32 prefix encoding for a key (acc|val|cons)") - cmd.Flags().BoolP(FlagAddress, "a", false, "Output the address only (overrides --output)") - cmd.Flags().BoolP(FlagETHAddress, "w", false, "Output the Ethereum address only (overrides --output)") - cmd.Flags().BoolP(FlagPublicKey, "p", false, "Output the public key only (overrides --output)") - cmd.Flags().BoolP(FlagDevice, "d", false, "Output the address in a ledger device") - cmd.Flags().Bool(flags.FlagIndentResponse, false, "Add indent to JSON response") - - return cmd -} - -func runShowCmd(cmd *cobra.Command, args []string) (err error) { - var info cosmosKeys.Info - - if len(args) == 1 { - info, err = GetKeyInfo(args[0]) - if err != nil { - return err - } - } else { - return errors.New("Must provide only one name") - } - - isShowAddr := viper.GetBool(FlagAddress) - isShowEthAddr := viper.GetBool(FlagETHAddress) - isShowPubKey := viper.GetBool(FlagPublicKey) - isShowDevice := viper.GetBool(FlagDevice) - - isOutputSet := false - tmp := cmd.Flag(cli.OutputFlag) - if tmp != nil { - isOutputSet = tmp.Changed - } - - isShowEitherAddr := isShowAddr || isShowEthAddr - - if isShowEitherAddr && isShowPubKey { - return errors.New("cannot get address, with --address or --ethwallet, and --pubkey at once") - } - - if isOutputSet && (isShowEitherAddr || isShowPubKey) { - return errors.New("cannot use --output with --address or --pubkey") - } - - keyOutputFunction := keys.Bech32KeyOutput - - switch { - case isShowAddr: - printKeyAddress(info, keyOutputFunction) - case isShowEthAddr: - printKeyEthAddress(info, keyOutputFunction) - case isShowPubKey: - printPubKey(info, keyOutputFunction) - default: - printKeyInfo(info, keyOutputFunction) - } - - if isShowDevice { - if isShowPubKey { - return fmt.Errorf("the device flag (-d) can only be used for addresses not pubkeys") - } - if viper.GetString(FlagBechPrefix) != "acc" { - return fmt.Errorf("the device flag (-d) can only be used for accounts") - } - // Override and show in the device - if info.GetType() != cosmosKeys.TypeLedger { - return fmt.Errorf("the device flag (-d) can only be used for accounts stored in devices") - } - - hdpath, err := info.GetPath() - if err != nil { - return nil - } - - return crypto.LedgerShowAddress(*hdpath, info.GetPubKey()) - } - - return nil -} - -// TODO: Determine if the different prefixes are necessary for ethermint -// func getBechKeyOut(bechPrefix string) (bechKeyOutFn, error) { -// switch bechPrefix { -// case sdk.PrefixAccount: -// return keys.Bech32KeyOutput, nil -// case sdk.PrefixValidator: -// return keys.Bech32ValKeyOutput, nil -// case sdk.PrefixConsensus: -// return keys.Bech32ConsKeyOutput, nil -// } - -// return nil, fmt.Errorf("invalid Bech32 prefix encoding provided: %s", bechPrefix) -// } diff --git a/keys/show_test.go b/keys/show_test.go deleted file mode 100644 index 6c605c38..00000000 --- a/keys/show_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package keys - -import ( - "testing" - - "github.com/spf13/viper" - "github.com/stretchr/testify/assert" - - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/tests" -) - -func TestShowKeysCmd(t *testing.T) { - cmd := showKeysCmd() - assert.NotNil(t, cmd) - assert.Equal(t, "false", cmd.Flag(FlagAddress).DefValue) - assert.Equal(t, "false", cmd.Flag(FlagPublicKey).DefValue) -} - -func TestRunShowCmd(t *testing.T) { - cmd := showKeysCmd() - - err := runShowCmd(cmd, []string{"invalid"}) - assert.EqualError(t, err, "Key invalid not found") - - // Prepare a key base - // Now add a temporary keybase - kbHome, cleanUp := tests.NewTestCaseDir(t) - defer cleanUp() - viper.Set(flags.FlagHome, kbHome) - - fakeKeyName1 := "runShowCmd_Key1" - fakeKeyName2 := "runShowCmd_Key2" - kb, err := NewKeyBaseFromHomeFlag() - assert.NoError(t, err) - _, err = kb.CreateAccount(fakeKeyName1, tests.TestMnemonic, "", "", 0, 0) - assert.NoError(t, err) - _, err = kb.CreateAccount(fakeKeyName2, tests.TestMnemonic, "", "", 0, 1) - assert.NoError(t, err) - - // // Now try single key - // err = runShowCmd(cmd, []string{fakeKeyName1}) - // assert.EqualError(t, err, "invalid Bech32 prefix encoding provided: ") - - // // Now try single key - set bech to acc - // viper.Set(FlagBechPrefix, sdk.PrefixAccount) - err = runShowCmd(cmd, []string{fakeKeyName1}) - assert.NoError(t, err) - err = runShowCmd(cmd, []string{fakeKeyName2}) - assert.NoError(t, err) -} diff --git a/keys/utils.go b/keys/utils.go deleted file mode 100644 index e8579104..00000000 --- a/keys/utils.go +++ /dev/null @@ -1,167 +0,0 @@ -package keys - -import ( - "fmt" - "path/filepath" - - "github.com/spf13/viper" - "github.com/tendermint/tendermint/libs/cli" - "gopkg.in/yaml.v2" - - clientkeys "github.com/cosmos/cosmos-sdk/client/keys" - - "github.com/cosmos/cosmos-sdk/client/flags" - cosmosKeys "github.com/cosmos/cosmos-sdk/crypto/keys" - emintKeys "github.com/cosmos/ethermint/crypto/keys" -) - -// available output formats. -const ( - OutputFormatText = "text" - OutputFormatJSON = "json" - - defaultKeyDBName = "emintkeys" -) - -type bechKeyOutFn func(keyInfo cosmosKeys.Info) (emintKeys.KeyOutput, error) - -// GetKeyInfo returns key info for a given name. An error is returned if the -// keybase cannot be retrieved or getting the info fails. -func GetKeyInfo(name string) (cosmosKeys.Info, error) { - keybase, err := NewKeyBaseFromHomeFlag() - if err != nil { - return nil, err - } - - return keybase.Get(name) -} - -// NewKeyBaseFromHomeFlag initializes a Keybase based on the configuration. -func NewKeyBaseFromHomeFlag() (cosmosKeys.Keybase, error) { - rootDir := viper.GetString(flags.FlagHome) - return NewKeyBaseFromDir(rootDir) -} - -// NewKeyBaseFromDir initializes a keybase at a particular dir. -func NewKeyBaseFromDir(rootDir string) (cosmosKeys.Keybase, error) { - return getLazyKeyBaseFromDir(rootDir) -} - -// NewInMemoryKeyBase returns a storage-less keybase. -func NewInMemoryKeyBase() cosmosKeys.Keybase { return emintKeys.NewInMemory() } - -func getLazyKeyBaseFromDir(rootDir string) (cosmosKeys.Keybase, error) { - return emintKeys.New(defaultKeyDBName, filepath.Join(rootDir, defaultKeyDBName)), nil -} - -// GetPassphrase returns a passphrase for a given name. It will first retrieve -// the key info for that name if the type is local, it'll fetch input from -// STDIN. Otherwise, an empty passphrase is returned. An error is returned if -// the key info cannot be fetched or reading from STDIN fails. -func GetPassphrase(name string) (string, error) { - var passphrase string - - keyInfo, err := GetKeyInfo(name) - if err != nil { - return passphrase, err - } - - // we only need a passphrase for locally stored keys - if keyInfo.GetType().String() == emintKeys.TypeLocal.String() { - passphrase, err = clientkeys.ReadPassphraseFromStdin(name) - if err != nil { - return passphrase, err - } - } - - return passphrase, nil -} - -func printKeyInfo(keyInfo cosmosKeys.Info, bechKeyOut bechKeyOutFn) { - ko, err := bechKeyOut(keyInfo) - if err != nil { - panic(err) - } - - switch viper.Get(cli.OutputFlag) { - case OutputFormatText: - printTextInfos([]emintKeys.KeyOutput{ko}) - - case OutputFormatJSON: - var out []byte - var err error - if viper.GetBool(flags.FlagIndentResponse) { - out, err = cdc.MarshalJSONIndent(ko, "", " ") - } else { - out, err = cdc.MarshalJSON(ko) - } - if err != nil { - panic(err) - } - - fmt.Println(string(out)) - } -} - -// func printInfos(infos []keys.Info) { -// kos, err := keys.Bech32KeysOutput(infos) -// if err != nil { -// panic(err) -// } - -// switch viper.Get(cli.OutputFlag) { -// case OutputFormatText: -// printTextInfos(kos) - -// case OutputFormatJSON: -// var out []byte -// var err error - -// if viper.GetBool(flags.FlagIndentResponse) { -// out, err = cdc.MarshalJSONIndent(kos, "", " ") -// } else { -// out, err = cdc.MarshalJSON(kos) -// } - -// if err != nil { -// panic(err) -// } -// fmt.Printf("%s", out) -// } -// } - -func printTextInfos(kos []emintKeys.KeyOutput) { - out, err := yaml.Marshal(&kos) - if err != nil { - panic(err) - } - - fmt.Println(string(out)) -} - -func printKeyAddress(info cosmosKeys.Info, bechKeyOut bechKeyOutFn) { - ko, err := bechKeyOut(info) - if err != nil { - panic(err) - } - - fmt.Println(ko.Address) -} - -func printKeyEthAddress(info cosmosKeys.Info, bechKeyOut bechKeyOutFn) { - ko, err := bechKeyOut(info) - if err != nil { - panic(err) - } - - fmt.Println(ko.ETHAddress) -} - -func printPubKey(info cosmosKeys.Info, bechKeyOut bechKeyOutFn) { - ko, err := bechKeyOut(info) - if err != nil { - panic(err) - } - - fmt.Println(ko.PubKey) -} diff --git a/rpc/config.go b/rpc/config.go index 2360850f..b773a64c 100644 --- a/rpc/config.go +++ b/rpc/config.go @@ -4,10 +4,10 @@ import ( "fmt" "github.com/cosmos/cosmos-sdk/client/flags" + emintkeys "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/client/lcd" "github.com/cosmos/cosmos-sdk/codec" emintcrypto "github.com/cosmos/ethermint/crypto" - emintkeys "github.com/cosmos/ethermint/keys" "github.com/ethereum/go-ethereum/rpc" "github.com/spf13/cobra" diff --git a/rpc/eth_api.go b/rpc/eth_api.go index f1f797c6..af04151e 100644 --- a/rpc/eth_api.go +++ b/rpc/eth_api.go @@ -8,8 +8,8 @@ import ( "strconv" "sync" + "github.com/cosmos/cosmos-sdk/client/keys" emintcrypto "github.com/cosmos/ethermint/crypto" - emintkeys "github.com/cosmos/ethermint/keys" params "github.com/cosmos/ethermint/rpc/args" emint "github.com/cosmos/ethermint/types" etypes "github.com/cosmos/ethermint/types" @@ -108,7 +108,7 @@ func (e *PublicEthAPI) Accounts() ([]common.Address, error) { e.keybaseLock.Lock() addresses := make([]common.Address, 0) // return [] instead of nil if empty - keybase, err := emintkeys.NewKeyBaseFromHomeFlag() + keybase, err := keys.NewKeyBaseFromHomeFlag() if err != nil { return addresses, err } diff --git a/types/account.go b/types/account.go index ad041912..93790303 100644 --- a/types/account.go +++ b/types/account.go @@ -6,6 +6,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth/exported" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ethcmn "github.com/ethereum/go-ethereum/common" ) @@ -23,6 +24,10 @@ const ( // Main Ethermint account // ---------------------------------------------------------------------------- +func init() { + authtypes.RegisterAccountTypeCodec(Account{}, EthermintAccountName) +} + // Account implements the auth.Account interface and embeds an // auth.BaseAccount type. It is compatible with the auth.AccountMapper. type Account struct { diff --git a/types/codec.go b/types/codec.go index e1855df9..de180843 100644 --- a/types/codec.go +++ b/types/codec.go @@ -10,8 +10,13 @@ func init() { RegisterCodec(typesCodec) } +const ( + // Amino encoding name + EthermintAccountName = "emint/Account" +) + // RegisterCodec registers all the necessary types with amino for the given // codec. func RegisterCodec(cdc *codec.Codec) { - cdc.RegisterConcrete(&Account{}, "types/Account", nil) + cdc.RegisterConcrete(&Account{}, EthermintAccountName, nil) } diff --git a/x/evm/client/cli/tx.go b/x/evm/client/cli/tx.go index 96426c17..e8a3ad5f 100644 --- a/x/evm/client/cli/tx.go +++ b/x/evm/client/cli/tx.go @@ -7,13 +7,13 @@ import ( "github.com/spf13/cobra" "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth/client/utils" - emintkeys "github.com/cosmos/ethermint/keys" emintTypes "github.com/cosmos/ethermint/types" - emintUtils "github.com/cosmos/ethermint/x/evm/client/utils" "github.com/cosmos/ethermint/x/evm/types" ethcmn "github.com/ethereum/go-ethereum/common" @@ -30,9 +30,8 @@ func GetTxCmd(storeKey string, cdc *codec.Codec) *cobra.Command { } evmTxCmd.AddCommand(client.PostCommands( - // TODO: Add back generating cosmos tx for Ethereum tx message - // GetCmdGenTx(cdc), - GetCmdGenETHTx(cdc), + // TODO: Add back generating cosmos tx for Ethereum tx message + // GetCmdGenTx(cdc), )...) return evmTxCmd @@ -46,11 +45,11 @@ func GetCmdGenTx(cdc *codec.Codec) *cobra.Command { Args: cobra.ExactArgs(5), RunE: func(cmd *cobra.Command, args []string) error { // TODO: remove inputs and infer based on StdTx - cliCtx := emintUtils.NewETHCLIContext().WithCodec(cdc) + cliCtx := context.NewCLIContext().WithCodec(cdc) txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) - kb, err := emintkeys.NewKeyBaseFromHomeFlag() + kb, err := keys.NewKeyBaseFromHomeFlag() if err != nil { panic(err) } @@ -80,63 +79,7 @@ func GetCmdGenTx(cdc *codec.Codec) *cobra.Command { } // TODO: possibly overwrite gas values in txBldr - return emintUtils.GenerateOrBroadcastETHMsgs(cliCtx, txBldr.WithKeybase(kb), []sdk.Msg{msg}) - }, - } -} - -// GetCmdGenTx generates an ethereum transaction -func GetCmdGenETHTx(cdc *codec.Codec) *cobra.Command { - return &cobra.Command{ - Use: "generate-eth-tx [amount] [gaslimit] [gasprice] [payload] []", - Short: "generate and broadcast an Ethereum tx. If address is not specified, contract will be created", - Args: cobra.RangeArgs(4, 5), - RunE: func(cmd *cobra.Command, args []string) error { - cliCtx := emintUtils.NewETHCLIContext().WithCodec(cdc) - - txBldr := auth.NewTxBuilderFromCLI().WithTxEncoder(utils.GetTxEncoder(cdc)) - - kb, err := emintkeys.NewKeyBaseFromHomeFlag() - if err != nil { - panic(err) - } - - coins, err := sdk.ParseCoins(args[0]) - if err != nil { - return err - } - - gasLimit, err := strconv.ParseUint(args[1], 0, 64) - if err != nil { - return err - } - - gasPrice, err := strconv.ParseUint(args[2], 0, 64) - if err != nil { - return err - } - - payload := args[3] - - txBldr, err = utils.PrepareTxBuilder(txBldr, cliCtx) - if err != nil { - return err - } - - var tx *types.EthereumTxMsg - if len(args) == 5 { - addr := ethcmn.HexToAddress(args[4]) - tx = types.NewEthereumTxMsg(txBldr.Sequence(), &addr, big.NewInt(coins.AmountOf(emintTypes.DenomDefault).Int64()), gasLimit, new(big.Int).SetUint64(gasPrice), []byte(payload)) - } else { - tx = types.NewEthereumTxMsgContract(txBldr.Sequence(), big.NewInt(coins.AmountOf(emintTypes.DenomDefault).Int64()), gasLimit, new(big.Int).SetUint64(gasPrice), []byte(payload)) - } - - err = tx.ValidateBasic() - if err != nil { - return err - } - - return emintUtils.BroadcastETHTx(cliCtx, txBldr.WithKeybase(kb), tx) + return utils.GenerateOrBroadcastMsgs(cliCtx, txBldr.WithKeybase(kb), []sdk.Msg{msg}) }, } } diff --git a/x/evm/client/utils/tx.go b/x/evm/client/utils/tx.go deleted file mode 100644 index ad627c69..00000000 --- a/x/evm/client/utils/tx.go +++ /dev/null @@ -1,344 +0,0 @@ -package utils - -import ( - "bufio" - "fmt" - "math/big" - "os" - - "github.com/pkg/errors" - "github.com/spf13/viper" - - "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/client/input" - crkeys "github.com/cosmos/cosmos-sdk/crypto/keys" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth/client/utils" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - emintcrypto "github.com/cosmos/ethermint/crypto" - emintkeys "github.com/cosmos/ethermint/keys" - emint "github.com/cosmos/ethermint/types" - evmtypes "github.com/cosmos/ethermint/x/evm/types" - - "github.com/tendermint/tendermint/libs/cli" - rpcclient "github.com/tendermint/tendermint/rpc/client" -) - -// * Code from this file is a modified version of cosmos-sdk/auth/client/utils/tx.go -// * to allow for using the Ethermint keybase for signing the transaction - -// GenerateOrBroadcastMsgs creates a StdTx given a series of messages. If -// the provided context has generate-only enabled, the tx will only be printed -// to STDOUT in a fully offline manner. Otherwise, the tx will be signed and -// broadcasted. -func GenerateOrBroadcastETHMsgs(cliCtx context.CLIContext, txBldr authtypes.TxBuilder, msgs []sdk.Msg) error { - if cliCtx.GenerateOnly { - return utils.PrintUnsignedStdTx(txBldr, cliCtx, msgs) - } - - return completeAndBroadcastETHTxCLI(txBldr, cliCtx, msgs) -} - -// BroadcastETHTx Broadcasts an Ethereum Tx not wrapped in a Std Tx -func BroadcastETHTx(cliCtx context.CLIContext, txBldr authtypes.TxBuilder, tx *evmtypes.EthereumTxMsg) error { - - fromName := cliCtx.GetFromName() - - passphrase, err := emintkeys.GetPassphrase(fromName) - if err != nil { - return err - } - - // Sign V, R, S fields for tx - ethTx, err := signEthTx(txBldr.Keybase(), fromName, passphrase, tx, txBldr.ChainID()) - if err != nil { - return err - } - - // Use default Tx Encoder since it will just be broadcasted to TM node at this point - txEncoder := txBldr.TxEncoder() - - txBytes, err := txEncoder(ethTx) - if err != nil { - return err - } - - // broadcast to a Tendermint node - res, err := cliCtx.BroadcastTx(txBytes) - if err != nil { - return err - } - - return cliCtx.PrintOutput(res) -} - -// completeAndBroadcastETHTxCLI implements a utility function that facilitates -// sending a series of messages in a signed transaction given a TxBuilder and a -// QueryContext. It ensures that the account exists, has a proper number and -// sequence set. In addition, it builds and signs a transaction with the -// supplied messages. Finally, it broadcasts the signed transaction to a node. -// * Modified version from github.com/cosmos/cosmos-sdk/x/auth/client/utils/tx.go -func completeAndBroadcastETHTxCLI(txBldr authtypes.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) error { - txBldr, err := utils.PrepareTxBuilder(txBldr, cliCtx) - if err != nil { - return err - } - - fromName := cliCtx.GetFromName() - - if txBldr.SimulateAndExecute() || cliCtx.Simulate { - txBldr, err = utils.EnrichWithGas(txBldr, cliCtx, msgs) - if err != nil { - return err - } - - gasEst := utils.GasEstimateResponse{GasEstimate: txBldr.Gas()} - _, _ = fmt.Fprintf(os.Stderr, "%s\n", gasEst.String()) - } - - if cliCtx.Simulate { - return nil - } - - if !cliCtx.SkipConfirm { - stdSignMsg, err := txBldr.BuildSignMsg(msgs) - if err != nil { - return err - } - - var json []byte - if viper.GetBool(flags.FlagIndentResponse) { - json, err = cliCtx.Codec.MarshalJSONIndent(stdSignMsg, "", " ") - if err != nil { - panic(err) - } - } else { - json = cliCtx.Codec.MustMarshalJSON(stdSignMsg) - } - - _, _ = fmt.Fprintf(os.Stderr, "%s\n\n", json) - - buf := bufio.NewReader(os.Stdin) - ok, err := input.GetConfirmation("confirm transaction before signing and broadcasting", buf) - if err != nil || !ok { - _, _ = fmt.Fprintf(os.Stderr, "%s\n", "cancelled transaction") - return err - } - } - - // * This function is overridden to change the keybase reference here - passphrase, err := emintkeys.GetPassphrase(fromName) - if err != nil { - return err - } - - // build and sign the transaction - // * needed to be modified also to change how the data is signed - txBytes, err := buildAndSign(txBldr, fromName, passphrase, msgs) - if err != nil { - return err - } - - // broadcast to a Tendermint node - res, err := cliCtx.BroadcastTx(txBytes) - if err != nil { - return err - } - - return cliCtx.PrintOutput(res) -} - -// BuildAndSign builds a single message to be signed, and signs a transaction -// with the built message given a name, passphrase, and a set of messages. -// * overridden from github.com/cosmos/cosmos-sdk/x/auth/types/txbuilder.go -// * This is just modified to change the functionality in makeSignature, through sign -func buildAndSign(bldr authtypes.TxBuilder, name, passphrase string, msgs []sdk.Msg) ([]byte, error) { - msg, err := bldr.BuildSignMsg(msgs) - if err != nil { - return nil, err - } - - return sign(bldr, name, passphrase, msg) -} - -// Sign signs a transaction given a name, passphrase, and a single message to -// signed. An error is returned if signing fails. -func sign(bldr authtypes.TxBuilder, name, passphrase string, msg authtypes.StdSignMsg) ([]byte, error) { - sig, err := makeSignature(bldr.Keybase(), name, passphrase, msg) - if err != nil { - return nil, err - } - - txEncoder := bldr.TxEncoder() - - return txEncoder(authtypes.NewStdTx(msg.Msgs, msg.Fee, []authtypes.StdSignature{sig}, msg.Memo)) -} - -// MakeSignature builds a StdSignature given keybase, key name, passphrase, and a StdSignMsg. -func makeSignature(keybase crkeys.Keybase, name, passphrase string, - msg authtypes.StdSignMsg) (sig authtypes.StdSignature, err error) { - if keybase == nil { - // * This is overridden to allow ethermint keys, but not used because keybase is set - keybase, err = emintkeys.NewKeyBaseFromHomeFlag() - if err != nil { - return - } - } - - // EthereumTxMsg always returns the data in the 0th index so it is safe to do this - var ethTx *evmtypes.EthereumTxMsg - ethTx, ok := msg.Msgs[0].(*evmtypes.EthereumTxMsg) - if !ok { - return sig, fmt.Errorf("Transaction message not an Ethereum Tx") - } - - // TODO: Move this logic to after tx is rlp decoded in keybase Sign function - // parse the chainID from a string to a base-10 integer - chainID, ok := new(big.Int).SetString(msg.ChainID, 10) - if !ok { - return sig, emint.ErrInvalidChainID(fmt.Sprintf("invalid chainID: %s", msg.ChainID)) - } - - privKey, err := keybase.ExportPrivateKeyObject(name, passphrase) - if err != nil { - return - } - - emintKey, ok := privKey.(emintcrypto.PrivKeySecp256k1) - if !ok { - panic(fmt.Sprintf("invalid private key type: %T", privKey)) - } - - ethTx.Sign(chainID, emintKey.ToECDSA()) - - // * This is needed to be overridden to get bytes to sign (RLPSignBytes) with the chainID - sigBytes, pubkey, err := keybase.Sign(name, passphrase, ethTx.RLPSignBytes(chainID).Bytes()) - if err != nil { - return - } - return authtypes.StdSignature{ - PubKey: pubkey, - Signature: sigBytes, - }, nil -} - -// signEthTx populates the V, R, and S fields of an EthereumTxMsg using an ethermint key -func signEthTx(keybase crkeys.Keybase, name, passphrase string, - ethTx *evmtypes.EthereumTxMsg, chainID string) (_ *evmtypes.EthereumTxMsg, err error) { - if keybase == nil { - keybase, err = emintkeys.NewKeyBaseFromHomeFlag() - if err != nil { - return - } - } - - // parse the chainID from a string to a base-10 integer - intChainID, ok := new(big.Int).SetString(chainID, 10) - if !ok { - return ethTx, emint.ErrInvalidChainID(fmt.Sprintf("invalid chainID: %s", chainID)) - } - - privKey, err := keybase.ExportPrivateKeyObject(name, passphrase) - if err != nil { - return - } - - // Key must be a ethermint key to be able to be converted into an ECDSA private key to sign - emintKey, ok := privKey.(emintcrypto.PrivKeySecp256k1) - if !ok { - panic(fmt.Sprintf("invalid private key type: %T", privKey)) - } - - ethTx.Sign(intChainID, emintKey.ToECDSA()) - - return ethTx, err -} - -// * This context is needed because the previous GetFromFields function would initialize a -// * default keybase to lookup the address or name. The new one overrides the keybase with the -// * ethereum compatible one - -// NewCLIContextWithFrom returns a new initialized CLIContext with parameters from the -// command line using Viper. It takes a key name or address and populates the FromName and -// FromAddress field accordingly. -func NewETHCLIContext() context.CLIContext { - var nodeURI string - var rpc rpcclient.Client - - from := viper.GetString(flags.FlagFrom) - - genOnly := viper.GetBool(flags.FlagGenerateOnly) - - // * This function is needed only to override this call to access correct keybase - fromAddress, fromName, err := getFromFields(from, genOnly) - if err != nil { - fmt.Printf("failed to get from fields: %v", err) - os.Exit(1) - } - - if !genOnly { - nodeURI = viper.GetString(flags.FlagNode) - if nodeURI != "" { - rpc = rpcclient.NewHTTP(nodeURI, "/websocket") - } - } - - return context.CLIContext{ - Client: rpc, - Output: os.Stdout, - NodeURI: nodeURI, - From: viper.GetString(flags.FlagFrom), - OutputFormat: viper.GetString(cli.OutputFlag), - Height: viper.GetInt64(flags.FlagHeight), - TrustNode: viper.GetBool(flags.FlagTrustNode), - UseLedger: viper.GetBool(flags.FlagUseLedger), - BroadcastMode: viper.GetString(flags.FlagBroadcastMode), - // Verifier: verifier, - Simulate: viper.GetBool(flags.FlagDryRun), - GenerateOnly: genOnly, - FromAddress: fromAddress, - FromName: fromName, - Indent: viper.GetBool(flags.FlagIndentResponse), - SkipConfirm: viper.GetBool(flags.FlagSkipConfirmation), - } -} - -// 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(from string, genOnly bool) (sdk.AccAddress, string, error) { - if from == "" { - return nil, "", nil - } - - if genOnly { - addr, err := sdk.AccAddressFromBech32(from) - if err != nil { - return nil, "", errors.Wrap(err, "must provide a valid Bech32 address for generate-only") - } - - return addr, "", nil - } - - // * This is the line that needed to be overridden, change could be to pass in optional keybase? - keybase, err := emintkeys.NewKeyBaseFromHomeFlag() - if err != nil { - return nil, "", err - } - - var info crkeys.Info - if addr, err := sdk.AccAddressFromBech32(from); err == nil { - info, err = keybase.GetByAddress(addr) - if err != nil { - return nil, "", err - } - } else { - info, err = keybase.Get(from) - if err != nil { - return nil, "", err - } - } - - return info.GetAddress(), info.GetName(), nil -} diff --git a/x/evm/types/codec.go b/x/evm/types/codec.go index eddab1d0..4ea5dd38 100644 --- a/x/evm/types/codec.go +++ b/x/evm/types/codec.go @@ -2,7 +2,6 @@ package types import ( "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/ethermint/crypto" ) // ModuleCdc defines the codec to be used by evm module @@ -21,5 +20,4 @@ func init() { func RegisterCodec(cdc *codec.Codec) { cdc.RegisterConcrete(&EthereumTxMsg{}, "ethermint/MsgEthereumTx", nil) cdc.RegisterConcrete(&EmintMsg{}, "ethermint/MsgEmint", nil) - crypto.RegisterCodec(cdc) }