Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Refactor tendermint api and keys modules to keep consistence with cosmos #574

Merged
merged 4 commits into from
Nov 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 46 additions & 15 deletions client/bank/lcd/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,48 @@ import (
"github.com/irisnet/irishub/client/bank"
"github.com/irisnet/irishub/client/context"
"github.com/irisnet/irishub/client/utils"
"strings"
)

// query accountREST Handler
func QueryBalancesRequestHandlerFn(
storeName string, cdc *codec.Codec,
decoder auth.AccountDecoder, cliCtx context.CLIContext,
) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
vars := mux.Vars(r)
bech32addr := vars["address"]

addr, err := sdk.AccAddressFromBech32(bech32addr)
if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}

res, err := cliCtx.QueryStore(auth.AddressStoreKey(addr), storeName)
if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}

// the query will return empty if there is no data for this account
if len(res) == 0 {
w.WriteHeader(http.StatusNoContent)
return
}

// decode the value
account, err := decoder(res)
if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}

utils.PostProcessResponse(w, cdc, account.GetCoins(), cliCtx.Indent)
}
}

// QueryAccountRequestHandlerFn performs account information query
func QueryAccountRequestHandlerFn(storeName string, cdc *codec.Codec,
decoder auth.AccountDecoder, cliCtx context.CLIContext,
Expand Down Expand Up @@ -52,14 +92,7 @@ func QueryAccountRequestHandlerFn(storeName string, cdc *codec.Codec,
return
}

// print out whole account
output, err := cdc.MarshalJSONIndent(accountRes, "", " ")
if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, fmt.Sprintf("couldn't marshall query result. Error: %s", err.Error()))
return
}

w.Write(output)
utils.PostProcessResponse(w, cdc, accountRes, cliCtx.Indent)
}
}

Expand All @@ -70,16 +103,14 @@ func QueryCoinTypeRequestHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext,
vars := mux.Vars(r)
coinType := vars["coin-type"]
res, err := cliCtx.GetCoinType(coinType)
if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
if strings.Contains(err.Error(),"unsupported coin type") {
w.WriteHeader(http.StatusNoContent)
return
}
output, err := codec.MarshalJSONIndent(cdc, res)
if err != nil {
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
} else if err != nil {
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}

w.Write(output)
utils.PostProcessResponse(w, cdc, res, cliCtx.Indent)
}
}
7 changes: 5 additions & 2 deletions client/bank/lcd/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import (

// RegisterRoutes - Central function to define routes that get registered by the main application
func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec) {
r.HandleFunc("/bank/{address}/send", SendRequestHandlerFn(cdc, cliCtx)).Methods("POST")
r.HandleFunc("/bank/accounts/{address}",
r.HandleFunc("/auth/accounts/{address}",
QueryAccountRequestHandlerFn("acc", cdc, authcmd.GetAccountDecoder(cdc), cliCtx)).Methods("GET")

r.HandleFunc("/bank/balances/{address}",
QueryBalancesRequestHandlerFn("acc", cdc, authcmd.GetAccountDecoder(cdc), cliCtx)).Methods("GET")
r.HandleFunc("/bank/accounts/{address}/transfers", SendRequestHandlerFn(cdc, cliCtx)).Methods("POST")
r.HandleFunc("/bank/coin/{coin-type}",
QueryCoinTypeRequestHandlerFn(cdc, cliCtx)).Methods("GET")

Expand Down
2 changes: 1 addition & 1 deletion client/distribution/lcd/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func QueryWithdrawAddressHandlerFn(storeName string, cliCtx context.CLIContext)
return
}
if len(res) == 0 {
utils.WriteErrorResponse(w, http.StatusNoContent, "No withdraw address specified. If the delegator does have valid delegations, then the withdraw address should be the same as the delegator address")
utils.WriteErrorResponse(w, http.StatusNoContent, "")
return
}
withdrawAddress := sdk.AccAddress(res)
Expand Down
2 changes: 1 addition & 1 deletion client/keys/cli/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func printCreate(info cryptokeys.Info, seed string) {
output := viper.Get(cli.OutputFlag)
switch output {
case "text":
keys.PrintInfo(cdc, info)
keys.PrintKeyInfo(info, keys.Bech32KeyOutput)
// print seed unless requested not to.
if !viper.GetBool(client.FlagUseLedger) && !viper.GetBool(flagNoBackup) {
fmt.Println("**Important** write this seed phrase in a safe place.")
Expand Down
11 changes: 6 additions & 5 deletions client/keys/cli/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,26 @@ package keys

import (
"fmt"

"github.com/irisnet/irishub/client/keys"
"github.com/spf13/cobra"
)

func deleteKeyCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "delete <name>",
Short: "Delete the given key",
Use: "delete <name>",
Short: "Delete the given key",
Example: "iriscli keys delete <key name>",
RunE: runDeleteCmd,
Args: cobra.ExactArgs(1),
RunE: runDeleteCmd,
Args: cobra.ExactArgs(1),
}
return cmd
}

func runDeleteCmd(cmd *cobra.Command, args []string) error {
name := args[0]

kb, err := keys.GetKeyBase()
kb, err := keys.GetKeyBaseWithWritePerm()
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion client/keys/cli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func Commands() *cobra.Command {
newKeyCommand(),
addKeyCommand(),
listKeysCmd,
showKeysCmd,
showKeysCmd(),
client.LineBreak,
deleteKeyCommand(),
updateKeyCommand(),
Expand Down
131 changes: 118 additions & 13 deletions client/keys/cli/show.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,127 @@
package keys

import (
"github.com/irisnet/irishub/client/keys"
"fmt"

cryptokeys "github.com/cosmos/cosmos-sdk/crypto/keys"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/tendermint/tendermint/crypto"
"github.com/tendermint/tendermint/crypto/multisig"

"github.com/irisnet/irishub/client/keys"
"github.com/tendermint/tmlibs/cli"

)

const (
// FlagAddress is the flag for the user's address on the command line.
FlagAddress = "address"
// 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"

flagMultiSigThreshold = "multisig-threshold"
defaultMultiSigKeyName = "multi"
)

var showKeysCmd = &cobra.Command{
Use: "show <name>",
Short: "Show key info for the given name",
Long: `Return public details of one local key.`,
Example: "iriscli keys show <key name>",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
name := args[0]
info, err := keys.GetKey(name)
if err == nil {
keys.PrintInfo(cdc, info)
var _ cryptokeys.Info = (*multiSigKey)(nil)

type multiSigKey struct {
name string
key crypto.PubKey
}

func (m multiSigKey) GetName() string { return m.name }
func (m multiSigKey) GetType() cryptokeys.KeyType { return cryptokeys.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.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().Uint(flagMultiSigThreshold, 1, "K out of N required signatures")

return cmd
}

func runShowCmd(cmd *cobra.Command, args []string) (err error) {
var info cryptokeys.Info

if len(args) == 1 {
info, err = keys.GetKeyInfo(args[0])
if err != nil {
return err
}
} else {
pks := make([]crypto.PubKey, len(args))
for i, keyName := range args {
info, err := keys.GetKeyInfo(keyName)
if err != nil {
return err
}
pks[i] = info.GetPubKey()
}

multisigThreshold := viper.GetInt(flagMultiSigThreshold)
err = validateMultisigThreshold(multisigThreshold, len(args))
if err != nil {
return err
}
multikey := multisig.NewPubKeyMultisigThreshold(multisigThreshold, pks)
info = multiSigKey{
name: defaultMultiSigKeyName,
key: multikey,
}
}

isShowAddr := viper.GetBool(FlagAddress)
isShowPubKey := viper.GetBool(FlagPublicKey)
isOutputSet := cmd.Flag(cli.OutputFlag).Changed

if isShowAddr && isShowPubKey {
return fmt.Errorf("cannot use both --address and --pubkey at once")
}

if isOutputSet && (isShowAddr || isShowPubKey) {
return fmt.Errorf("cannot use --output with --address or --pubkey")
}

bechKeyOut, err := keys.GetBechKeyOut(viper.GetString(FlagBechPrefix))
if err != nil {
return err
},
}

switch {
case isShowAddr:
keys.PrintKeyAddress(info, bechKeyOut)
case isShowPubKey:
keys.PrintPubKey(info, bechKeyOut)
default:
keys.PrintKeyInfo(info, bechKeyOut)
}

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
}
2 changes: 1 addition & 1 deletion client/keys/cli/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func runUpdateCmd(cmd *cobra.Command, args []string) error {
name := args[0]

buf := keys.BufferStdin()
kb, err := keys.GetKeyBase()
kb, err := keys.GetKeyBaseWithWritePerm()
if err != nil {
return err
}
Expand Down
19 changes: 19 additions & 0 deletions client/keys/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package keys

import "fmt"

func ErrKeyNameConflict(name string) error {
return fmt.Errorf("acount with name %s already exists", name)
}

func ErrMissingName() error {
return fmt.Errorf("you have to specify a name for the locally stored account")
}

func ErrMissingPassword() error {
return fmt.Errorf("you have to specify a password for the locally stored account")
}

func ErrMissingSeed() error {
return fmt.Errorf("you have to specify seed for key recover")
}
Loading