Skip to content

Commit

Permalink
make cli support tss key
Browse files Browse the repository at this point in the history
  • Loading branch information
ackratos committed Jul 8, 2019
1 parent 8e2ea76 commit 6b5995f
Show file tree
Hide file tree
Showing 11 changed files with 873 additions and 18 deletions.
751 changes: 742 additions & 9 deletions Gopkg.lock

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

[[constraint]]
name = "github.com/spf13/viper"
version = "~1.0.0"
version = "~1.4.0"

[[constraint]]
name = "github.com/pkg/errors"
Expand Down Expand Up @@ -122,4 +122,6 @@
go-tests = true
unused-packages = true


[[constraint]]
branch = "master"
name = "github.com/binance-chain/tss"
2 changes: 2 additions & 0 deletions client/context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type CLIContext struct {
AccountStore string
TrustNode bool
UseLedger bool
UseTss bool
Async bool
JSON bool
PrintResponse bool
Expand Down Expand Up @@ -83,6 +84,7 @@ func NewCLIContext() CLIContext {
Height: viper.GetInt64(client.FlagHeight),
TrustNode: viper.GetBool(client.FlagTrustNode),
UseLedger: viper.GetBool(client.FlagUseLedger),
UseTss: viper.GetBool(client.FlagUseTss),
Async: viper.GetBool(client.FlagAsync),
JSON: viper.GetBool(client.FlagJson),
PrintResponse: viper.GetBool(client.FlagPrintResponse),
Expand Down
5 changes: 5 additions & 0 deletions client/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
// nolint
const (
FlagUseLedger = "ledger"
FlagUseTss = "tss"
FlagChainID = "chain-id"
FlagNode = "node"
FlagHeight = "height"
Expand Down Expand Up @@ -39,11 +40,13 @@ func GetCommands(cmds ...*cobra.Command) []*cobra.Command {
c.Flags().Bool(FlagIndentResponse, false, "Add indent to JSON response")
c.Flags().Bool(FlagTrustNode, false, "Trust connected full node (don't verify proofs for responses)")
c.Flags().Bool(FlagUseLedger, false, "Use a connected Ledger device")
c.Flags().Bool(FlagUseTss, false, "Use tss vault")
c.Flags().String(FlagChainID, "", "Chain ID of tendermint node")
c.Flags().String(FlagNode, "tcp://localhost:26657", "<host>:<port> to tendermint rpc interface for this chain")
c.Flags().Int64(FlagHeight, 0, "block height to query, omit to get most recent provable block")
viper.BindPFlag(FlagTrustNode, c.Flags().Lookup(FlagTrustNode))
viper.BindPFlag(FlagUseLedger, c.Flags().Lookup(FlagUseLedger))
viper.BindPFlag(FlagUseTss, c.Flags().Lookup(FlagUseTss))
viper.BindPFlag(FlagChainID, c.Flags().Lookup(FlagChainID))
viper.BindPFlag(FlagNode, c.Flags().Lookup(FlagNode))
}
Expand All @@ -62,6 +65,7 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command {
c.Flags().String(FlagChainID, "", "Chain ID of tendermint node")
c.Flags().String(FlagNode, "tcp://localhost:26657", "<host>:<port> to tendermint rpc interface for this chain")
c.Flags().Bool(FlagUseLedger, false, "Use a connected Ledger device")
c.Flags().Bool(FlagUseTss, false, "Use a tss vault")
c.Flags().Bool(FlagAsync, false, "broadcast transactions asynchronously")
c.Flags().Bool(FlagJson, false, "return output in json format")
c.Flags().Bool(FlagPrintResponse, true, "return tx response (only works with async = false)")
Expand All @@ -71,6 +75,7 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command {
c.Flags().Bool(FlagGenerateOnly, false, "build an unsigned transaction and write it to STDOUT")
viper.BindPFlag(FlagTrustNode, c.Flags().Lookup(FlagTrustNode))
viper.BindPFlag(FlagUseLedger, c.Flags().Lookup(FlagUseLedger))
viper.BindPFlag(FlagUseTss, c.Flags().Lookup(FlagUseTss))
viper.BindPFlag(FlagChainID, c.Flags().Lookup(FlagChainID))
viper.BindPFlag(FlagNode, c.Flags().Lookup(FlagNode))
}
Expand Down
21 changes: 19 additions & 2 deletions client/keys/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"io/ioutil"
"net/http"
"os"

"github.com/cosmos/cosmos-sdk/client"
"github.com/gorilla/mux"
Expand All @@ -24,6 +25,7 @@ const (
flagDryRun = "dry-run"
flagAccount = "account"
flagIndex = "index"
flagTssHome = "tss-home"
)

func addKeyCommand() *cobra.Command {
Expand All @@ -37,11 +39,13 @@ phrase, otherwise, a new key will be generated.`,
}
cmd.Flags().StringP(flagType, "t", "secp256k1", "Type of private key (secp256k1|ed25519)")
cmd.Flags().Bool(client.FlagUseLedger, false, "Store a local reference to a private key on a Ledger device")
cmd.Flags().Bool(client.FlagUseTss, false, "Store a local reference to a private key on a Tss vault")
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, "Index number for HD derivation")
cmd.Flags().String(flagTssHome, "", "Path to home of tss client")
return cmd
}

Expand Down Expand Up @@ -78,7 +82,7 @@ func runAddCmd(cmd *cobra.Command, args []string) error {
}

// ask for a password when generating a local key
if !viper.GetBool(client.FlagUseLedger) {
if !(viper.GetBool(client.FlagUseLedger) || viper.GetBool(client.FlagUseTss)) {
pass, err = client.GetCheckPassword(
"Enter a passphrase for your key:",
"Repeat the passphrase:", buf)
Expand All @@ -98,6 +102,19 @@ func runAddCmd(cmd *cobra.Command, args []string) error {
return err
}
printCreate(info, "")
} else if viper.GetBool(client.FlagUseTss) {
home := viper.GetString(flagTssHome)
if home == "" {
return fmt.Errorf("tss home is not set")
}
if _, err := os.Stat(home); os.IsNotExist(err) {
return fmt.Errorf("tss home: %s is not exist", home)
}
info, err := kb.CreateTss(name, home)
if err != nil {
return err
}
printCreate(info, "")
} else if viper.GetBool(flagRecover) {
seed, err := client.GetSeed(
"Enter your recovery seed phrase:", buf)
Expand Down Expand Up @@ -129,7 +146,7 @@ func printCreate(info keys.Info, seed string) {
printKeyInfo(info, Bech32KeyOutput)

// print seed unless requested not to.
if !viper.GetBool(client.FlagUseLedger) && !viper.GetBool(flagNoBackup) {
if !viper.GetBool(client.FlagUseLedger) && !viper.GetBool(client.FlagUseTss) && !viper.GetBool(flagNoBackup) {
fmt.Println("**Important** write this seed phrase in a safe place.")
fmt.Println("It is the only way to recover your account if you ever forget your password.")
fmt.Println()
Expand Down
4 changes: 2 additions & 2 deletions client/keys/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ func GetPassphrase(name string) (string, error) {
return passphrase, err
}

// we only need a passphrase for locally stored keys
// we need a passphrase for locally stored and tss keys
// TODO: (ref: #864) address security concerns
if keyInfo.GetType() == keys.TypeLocal {
if keyInfo.GetType() == keys.TypeLocal || keyInfo.GetType() == keys.TypeTss {
passphrase, err = ReadPassphraseFromStdin(name)
if err != nil {
return passphrase, err
Expand Down
1 change: 1 addition & 0 deletions crypto/keys/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ func init() {
cdc.RegisterConcrete(localInfo{}, "crypto/keys/localInfo", nil)
cdc.RegisterConcrete(ledgerInfo{}, "crypto/keys/ledgerInfo", nil)
cdc.RegisterConcrete(offlineInfo{}, "crypto/keys/offlineInfo", nil)
cdc.RegisterConcrete(tssInfo{}, "crypto/keys/tssInfo", nil)
}
19 changes: 19 additions & 0 deletions crypto/keys/keybase.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ func (kb dbKeybase) CreateLedger(name string, path crypto.DerivationPath, algo S
return kb.writeLedgerKey(pub, path, name), nil
}

func (kb dbKeybase) CreateTss(name string, path string) (info Info, err error) {
return kb.writeTssKey(name, path), 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) (Info, error) {
Expand Down Expand Up @@ -257,6 +261,12 @@ func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig []byte, pub t
if err != nil {
return
}
case tssInfo:
linfo := info.(tssInfo)
priv, err = crypto.NewPrivKeyTss(linfo.Path, passphrase)
if err != nil {
return
}
case offlineInfo:
linfo := info.(offlineInfo)
_, err := fmt.Fprintf(os.Stderr, "Bytes to sign:\n%s", msg)
Expand Down Expand Up @@ -303,6 +313,8 @@ func (kb dbKeybase) ExportPrivateKeyObject(name string, passphrase string) (tmcr
}
case ledgerInfo:
return nil, errors.New("Only works on local private keys")
case tssInfo:
return nil, errors.New("Only works on local private keys")
case offlineInfo:
return nil, errors.New("Only works on local private keys")
}
Expand Down Expand Up @@ -386,6 +398,7 @@ func (kb dbKeybase) Delete(name, passphrase string) error {
kb.db.DeleteSync(infoKey(name))
return nil
case ledgerInfo:
case tssInfo:
case offlineInfo:
if passphrase != "yes" {
return fmt.Errorf("enter 'yes' exactly to delete the key - this cannot be undone")
Expand Down Expand Up @@ -448,6 +461,12 @@ func (kb dbKeybase) writeLedgerKey(pub tmcrypto.PubKey, path crypto.DerivationPa
return info
}

func (kb dbKeybase) writeTssKey(name, path string) Info {
info := newTssInfo(name, path)
kb.writeInfo(info, name)
return info
}

func (kb dbKeybase) writeOfflineKey(pub tmcrypto.PubKey, name string) Info {
info := newOfflineInfo(name, pub)
kb.writeInfo(info, name)
Expand Down
41 changes: 40 additions & 1 deletion crypto/keys/types.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package keys

import (
"github.com/binance-chain/tss/client"
ccrypto "github.com/cosmos/cosmos-sdk/crypto"
"github.com/tendermint/tendermint/crypto"

Expand Down Expand Up @@ -34,7 +35,7 @@ type Keybase interface {
encryptPasswd string, params hd.BIP44Params) (Info, error)
// Create, store, and return a new Ledger key reference
CreateLedger(name string, path ccrypto.DerivationPath, algo SigningAlgo) (info Info, err error)

CreateTss(name string, path string) (info Info, err error)
// Create, store, and return a new offline key reference
CreateOffline(name string, pubkey crypto.PubKey) (info Info, err error)

Expand All @@ -60,12 +61,14 @@ const (
TypeLocal KeyType = 0
TypeLedger KeyType = 1
TypeOffline KeyType = 2
TypeTss KeyType = 3
)

var keyTypes = map[KeyType]string{
TypeLocal: "local",
TypeLedger: "ledger",
TypeOffline: "offline",
TypeTss: "tss",
}

// String implements the stringer interface for KeyType.
Expand All @@ -88,6 +91,7 @@ type Info interface {
var _ Info = &localInfo{}
var _ Info = &ledgerInfo{}
var _ Info = &offlineInfo{}
var _ Info = &tssInfo{}

// localInfo is the public information about a locally stored key
type localInfo struct {
Expand Down Expand Up @@ -180,6 +184,41 @@ func (i offlineInfo) GetAddress() types.AccAddress {
return i.PubKey.Address().Bytes()
}

// tssInfo is the public information about a tss key
type tssInfo struct {
Name string `json:"name"`
PubKey crypto.PubKey `json:"pubkey"`
Path string `json:"path"` // path to home of tss client
}

func (i tssInfo) GetType() KeyType {
return TypeTss
}

func (i tssInfo) GetName() string {
return i.Name
}

func (i tssInfo) GetPubKey() crypto.PubKey {
return i.PubKey
}

func (i tssInfo) GetAddress() types.AccAddress {
return i.PubKey.Address().Bytes()
}

func newTssInfo(name, path string) Info {
pubKey, err := client.LoadPubkey(path)
if err != nil {
return nil
}
return &tssInfo{
Name: name,
PubKey: pubKey,
Path: path,
}
}

// encoding info
func writeInfo(i Info) []byte {
return cdc.MustMarshalBinaryLengthPrefixed(i)
Expand Down
5 changes: 3 additions & 2 deletions crypto/ledger_secp256k1.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import (
"strings"

"github.com/btcsuite/btcd/btcec"
sdk "github.com/cosmos/cosmos-sdk/types"
ledgergo "github.com/zondax/ledger-cosmos-go"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/pkg/errors"
tmbtcec "github.com/tendermint/btcd/btcec"
tmcrypto "github.com/tendermint/tendermint/crypto"
Expand Down Expand Up @@ -129,7 +130,7 @@ func (pkl PrivKeyLedgerSecp256k1) Sign(msg []byte) ([]byte, error) {
if err != nil {
return nil, err
}
if ledgerAppVersion.Major > 1 || ledgerAppVersion.Major == 1 && ledgerAppVersion.Minor >= 1 {
if ledgerAppVersion.Major > 1 || ledgerAppVersion.Major == 1 && ledgerAppVersion.Minor >= 1 {
fmt.Print(fmt.Sprintf("Please confirm if address displayed on ledger is identical to %s (yes/no)?", sdk.AccAddress(pkl.CachedPubKey.Address()).String()))
err = pkl.ledger.ShowAddressSECP256K1(pkl.Path, sdk.GetConfig().GetBech32AccountAddrPrefix())
if err != nil {
Expand Down
36 changes: 36 additions & 0 deletions crypto/tss.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package crypto

import (
"github.com/spf13/viper"

"github.com/ipfs/go-log"

tmcrypto "github.com/tendermint/tendermint/crypto"

_ "github.com/binance-chain/tss-lib/signing"
"github.com/binance-chain/tss/client"
"github.com/binance-chain/tss/common"
)

func NewPrivKeyTss(home, passphrase string) (tmcrypto.PrivKey, error) {
config, err := common.ReadConfigFromHome(viper.New(), home)
if err != nil {
return nil, err
}
config.Password = passphrase
initLogLevel(config)
return client.NewTssClient(config, false), nil
}

func initLogLevel(cfg common.TssConfig) {
log.SetLogLevel("tss", cfg.P2PConfig.LogLevel)
log.SetLogLevel("tss-lib", cfg.P2PConfig.LogLevel)
log.SetLogLevel("srv", cfg.P2PConfig.LogLevel)
log.SetLogLevel("trans", cfg.P2PConfig.LogLevel)
log.SetLogLevel("p2p_utils", cfg.P2PConfig.LogLevel)

// libp2p loggers
log.SetLogLevel("dht", "error")
log.SetLogLevel("discovery", "error")
log.SetLogLevel("swarm2", "error")
}

0 comments on commit 6b5995f

Please sign in to comment.