From 322a029ab5f4476372c15b9132129d7408c311a1 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 22 Oct 2018 11:50:21 -0700 Subject: [PATCH 01/10] Make gaiacli keys show multisig-ready --- client/keys/show.go | 54 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/client/keys/show.go b/client/keys/show.go index b567daf12435..f81df32631d2 100644 --- a/client/keys/show.go +++ b/client/keys/show.go @@ -2,6 +2,8 @@ package keys import ( "fmt" + "github.com/cosmos/cosmos-sdk/crypto/keys" + "github.com/tendermint/tendermint/crypto" "net/http" "github.com/gorilla/mux" @@ -9,39 +11,73 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/tendermint/tendermint/libs/cli" + "github.com/tendermint/tendermint/crypto/multisig" + sdk "github.com/cosmos/cosmos-sdk/types" ) const ( // FlagAddress is the flag for the user's address on the command line. - FlagAddress = "address" + FlagAddress = "address" // FlagPublicKey represents the user's public key on the command line. - FlagPublicKey = "pubkey" + FlagPublicKey = "pubkey" // FlagBechPrefix defines a desired Bech32 prefix encoding for a key. - FlagBechPrefix = "bech" + FlagBechPrefix = "bech" + + flagMultiSigThreshold = "multisig-threshold" ) +var _ keys.Info = (keys.Info)(nil) + +type multiSigKey struct { + name string + key crypto.PubKey +} + +func (m multiSigKey) GetName() string { return m.name } +func (m multiSigKey) GetType() keys.KeyType { return keys.TypeLocal } +func (m multiSigKey) GetPubKey() crypto.PubKey { return m.key } +func (m multiSigKey) GetAddress() sdk.AccAddress { return sdk.AccAddress(m.key.Address())} + + func showKeysCmd() *cobra.Command { cmd := &cobra.Command{ Use: "show [name]", Short: "Show key info for the given name", Long: `Return public details of one local key.`, - Args: cobra.ExactArgs(1), + Args: cobra.MinimumNArgs(1), RunE: runShowCmd, } cmd.Flags().String(FlagBechPrefix, "acc", "The Bech32 prefix encoding for a key (acc|val|cons)") cmd.Flags().Bool(FlagAddress, false, "output the address only (overrides --output)") cmd.Flags().Bool(FlagPublicKey, false, "output the public key only (overrides --output)") + cmd.Flags().UintP(flagMultiSigThreshold, "m", 1, "K out of N required signatures") return cmd } -func runShowCmd(cmd *cobra.Command, args []string) error { - name := args[0] +func runShowCmd(cmd *cobra.Command, args []string) (err error) { + var info keys.Info - info, err := GetKeyInfo(name) - if err != nil { - return err + if len(args) == 1 { + info, err = GetKeyInfo(args[0]) + if err != nil { + return err + } + } else { + pks := make([]crypto.PubKey, len(args)) + for i, keyName := range args { + info, err := GetKeyInfo(keyName) + if err != nil { + return err + } + pks[i] = info.GetPubKey() + } + multikey := multisig.NewPubKeyMultisigThreshold(viper.GetInt(flagMultiSigThreshold), pks) + info = multiSigKey{ + name: "multi", + key: multikey, + } } isShowAddr := viper.GetBool(FlagAddress) From 6ae767d89c24f7b34a58be295d8a43d9e45c3dec Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 22 Oct 2018 13:34:41 -0700 Subject: [PATCH 02/10] Update PENDING.md --- PENDING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/PENDING.md b/PENDING.md index d773e4645261..980e2bed1362 100644 --- a/PENDING.md +++ b/PENDING.md @@ -128,6 +128,7 @@ FEATURES * [stake][cli] [\#1672](https://github.com/cosmos/cosmos-sdk/issues/1672) Introduced new commission flags for validator commands `create-validator` and `edit-validator`. * [stake][cli] [\#1890](https://github.com/cosmos/cosmos-sdk/issues/1890) Add `--genesis-format` flag to `gaiacli tx create-validator` to produce transactions in genesis-friendly format. + * [cli][\#2554](https://github.com/cosmos/cosmos-sdk/issues/2554) Make `gaiacli keys show` multisig ready. * Gaia * [cli] #2170 added ability to show the node's address via `gaiad tendermint show-address` From 50a2f9641b784e5d24c54910f966cbdc048da246 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 22 Oct 2018 13:35:22 -0700 Subject: [PATCH 03/10] Refresh Gopkg.lock --- Gopkg.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/Gopkg.lock b/Gopkg.lock index c679450b9c0e..bee366923ae1 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -682,6 +682,7 @@ "github.com/tendermint/tendermint/crypto/ed25519", "github.com/tendermint/tendermint/crypto/encoding/amino", "github.com/tendermint/tendermint/crypto/merkle", + "github.com/tendermint/tendermint/crypto/multisig", "github.com/tendermint/tendermint/crypto/secp256k1", "github.com/tendermint/tendermint/crypto/tmhash", "github.com/tendermint/tendermint/crypto/xsalsa20symmetric", From 8d244658450f174aa40a6ef3c49f000d5ae3d5eb Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 22 Oct 2018 13:37:28 -0700 Subject: [PATCH 04/10] Run make format --- client/keys/show.go | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/client/keys/show.go b/client/keys/show.go index f81df32631d2..6159b092047e 100644 --- a/client/keys/show.go +++ b/client/keys/show.go @@ -6,38 +6,37 @@ import ( "github.com/tendermint/tendermint/crypto" "net/http" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/gorilla/mux" "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/tendermint/tendermint/libs/cli" "github.com/tendermint/tendermint/crypto/multisig" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/tendermint/tendermint/libs/cli" ) const ( // FlagAddress is the flag for the user's address on the command line. - FlagAddress = "address" + FlagAddress = "address" // FlagPublicKey represents the user's public key on the command line. - FlagPublicKey = "pubkey" + FlagPublicKey = "pubkey" // FlagBechPrefix defines a desired Bech32 prefix encoding for a key. - FlagBechPrefix = "bech" + FlagBechPrefix = "bech" - flagMultiSigThreshold = "multisig-threshold" + flagMultiSigThreshold = "multisig-threshold" ) var _ keys.Info = (keys.Info)(nil) type multiSigKey struct { name string - key crypto.PubKey + key crypto.PubKey } func (m multiSigKey) GetName() string { return m.name } func (m multiSigKey) GetType() keys.KeyType { return keys.TypeLocal } func (m multiSigKey) GetPubKey() crypto.PubKey { return m.key } -func (m multiSigKey) GetAddress() sdk.AccAddress { return sdk.AccAddress(m.key.Address())} - +func (m multiSigKey) GetAddress() sdk.AccAddress { return sdk.AccAddress(m.key.Address()) } func showKeysCmd() *cobra.Command { cmd := &cobra.Command{ @@ -51,7 +50,7 @@ func showKeysCmd() *cobra.Command { cmd.Flags().String(FlagBechPrefix, "acc", "The Bech32 prefix encoding for a key (acc|val|cons)") cmd.Flags().Bool(FlagAddress, false, "output the address only (overrides --output)") cmd.Flags().Bool(FlagPublicKey, false, "output the public key only (overrides --output)") - cmd.Flags().UintP(flagMultiSigThreshold, "m", 1, "K out of N required signatures") + cmd.Flags().UintP(flagMultiSigThreshold, "m", 1, "K out of N required signatures") return cmd } @@ -76,7 +75,7 @@ func runShowCmd(cmd *cobra.Command, args []string) (err error) { multikey := multisig.NewPubKeyMultisigThreshold(viper.GetInt(flagMultiSigThreshold), pks) info = multiSigKey{ name: "multi", - key: multikey, + key: multikey, } } From ca049fd453f8b63c5be47d6ec0699fc5e12ec84d Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 22 Oct 2018 13:43:18 -0700 Subject: [PATCH 05/10] Add some docs --- docs/sdk/clients.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/sdk/clients.md b/docs/sdk/clients.md index 9637b3b4beb8..f9226947db90 100644 --- a/docs/sdk/clients.md +++ b/docs/sdk/clients.md @@ -74,6 +74,16 @@ gaiad tendermint show-validator We strongly recommend _NOT_ using the same passphrase for multiple keys. The Tendermint team and the Interchain Foundation will not be responsible for the loss of funds. ::: +#### Multisig public keys + +You can generate and print a multisig public key by typing: + +```bash +gaiacli show -m K key1 key2...keyK +``` + +`K` is the minimum number of private keys that must have signed the transactions that carry the generated public key. + ### Account #### Get Tokens From 230c69b438e553c45f6f19a3c8d97f4f717d2099 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Mon, 22 Oct 2018 17:13:36 -0700 Subject: [PATCH 06/10] Validate threshold rather than letting it panic --- client/keys/show.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/client/keys/show.go b/client/keys/show.go index 6159b092047e..fe8641831281 100644 --- a/client/keys/show.go +++ b/client/keys/show.go @@ -72,7 +72,13 @@ func runShowCmd(cmd *cobra.Command, args []string) (err error) { } pks[i] = info.GetPubKey() } - multikey := multisig.NewPubKeyMultisigThreshold(viper.GetInt(flagMultiSigThreshold), pks) + + multisigThreshold := viper.GetInt(flagMultiSigThreshold) + err = validateMultisigThreshold(multisigThreshold, len(args)) + if err != nil { + return err + } + multikey := multisig.NewPubKeyMultisigThreshold(multisigThreshold, pks) info = multiSigKey{ name: "multi", key: multikey, @@ -108,6 +114,17 @@ func runShowCmd(cmd *cobra.Command, args []string) (err error) { return nil } +func validateMultisigThreshold(k, nKeys int) error { + if k <= 0 { + return fmt.Errorf("threshold must be a positive integer") + } + if nKeys < k { + return fmt.Errorf( + "threshold k of n multisignature: %d < %d", nKeys, k) + } + return nil +} + func getBechKeyOut(bechPrefix string) (bechKeyOutFn, error) { switch bechPrefix { case "acc": From 6ace08b5051e809878108c076625ac18957e7cda Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Tue, 23 Oct 2018 11:44:47 -0700 Subject: [PATCH 07/10] Remove shorthand --- client/keys/show.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/keys/show.go b/client/keys/show.go index fe8641831281..6c1c97c22465 100644 --- a/client/keys/show.go +++ b/client/keys/show.go @@ -50,7 +50,7 @@ func showKeysCmd() *cobra.Command { cmd.Flags().String(FlagBechPrefix, "acc", "The Bech32 prefix encoding for a key (acc|val|cons)") cmd.Flags().Bool(FlagAddress, false, "output the address only (overrides --output)") cmd.Flags().Bool(FlagPublicKey, false, "output the public key only (overrides --output)") - cmd.Flags().UintP(flagMultiSigThreshold, "m", 1, "K out of N required signatures") + cmd.Flags().Uint(flagMultiSigThreshold, 1, "K out of N required signatures") return cmd } From cd49e978f9dda3605ca7401b0030254a523ffbf5 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Tue, 23 Oct 2018 11:46:43 -0700 Subject: [PATCH 08/10] Make "multi" const --- client/keys/show.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/keys/show.go b/client/keys/show.go index 6c1c97c22465..a922cf3ac37f 100644 --- a/client/keys/show.go +++ b/client/keys/show.go @@ -23,7 +23,8 @@ const ( // FlagBechPrefix defines a desired Bech32 prefix encoding for a key. FlagBechPrefix = "bech" - flagMultiSigThreshold = "multisig-threshold" + flagMultiSigThreshold = "multisig-threshold" + defaultMultiSigKeyName = "multi" ) var _ keys.Info = (keys.Info)(nil) @@ -80,7 +81,7 @@ func runShowCmd(cmd *cobra.Command, args []string) (err error) { } multikey := multisig.NewPubKeyMultisigThreshold(multisigThreshold, pks) info = multiSigKey{ - name: "multi", + name: defaultMultiSigKeyName, key: multikey, } } From 6664cd5afdd7da3ff73f69abb0d79f77b037cf57 Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Tue, 23 Oct 2018 12:43:36 -0700 Subject: [PATCH 09/10] Fix stupid mistake --- client/keys/show.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/keys/show.go b/client/keys/show.go index a922cf3ac37f..7600a762fc4a 100644 --- a/client/keys/show.go +++ b/client/keys/show.go @@ -27,7 +27,7 @@ const ( defaultMultiSigKeyName = "multi" ) -var _ keys.Info = (keys.Info)(nil) +var _ keys.Info = (*multiSigKey)(nil) type multiSigKey struct { name string From 68f869a24d358d442ac80dc842b3f38983ddac6c Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Tue, 23 Oct 2018 18:15:23 -0700 Subject: [PATCH 10/10] s/number/weight/ --- docs/sdk/clients.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sdk/clients.md b/docs/sdk/clients.md index f9226947db90..4703c492185c 100644 --- a/docs/sdk/clients.md +++ b/docs/sdk/clients.md @@ -82,7 +82,7 @@ You can generate and print a multisig public key by typing: gaiacli show -m K key1 key2...keyK ``` -`K` is the minimum number of private keys that must have signed the transactions that carry the generated public key. +`K` is the minimum weight, e.g. minimum number of private keys that must have signed the transactions that carry the generated public key. ### Account