cosmos-sdk/cmd/commands/utils.go

196 lines
4.8 KiB
Go
Raw Normal View History

package commands
2017-01-29 13:34:48 -08:00
import (
"encoding/hex"
"fmt"
"os"
2017-04-17 18:28:03 -07:00
"path"
"regexp"
"strconv"
"strings"
2017-01-29 13:34:48 -08:00
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
2017-01-29 18:41:37 -08:00
"github.com/tendermint/basecoin/state"
2017-01-29 13:34:48 -08:00
"github.com/tendermint/basecoin/types"
2017-01-29 18:41:37 -08:00
abci "github.com/tendermint/abci/types"
2017-04-15 09:07:27 -07:00
cmn "github.com/tendermint/go-common"
2017-01-29 13:34:48 -08:00
client "github.com/tendermint/go-rpc/client"
2017-03-16 01:01:29 -07:00
wire "github.com/tendermint/go-wire"
2017-01-29 13:34:48 -08:00
ctypes "github.com/tendermint/tendermint/rpc/core/types"
2017-01-29 18:41:37 -08:00
tmtypes "github.com/tendermint/tendermint/types"
2017-01-29 13:34:48 -08:00
)
//This variable can be overwritten by plugin applications
// if they require a different working directory
2017-04-17 18:28:03 -07:00
var DefaultHome = ".basecoin"
func BasecoinRoot(rootDir string) string {
if rootDir == "" {
2017-03-13 22:50:10 -07:00
rootDir = os.Getenv("BCHOME")
}
if rootDir == "" {
2017-04-17 18:28:03 -07:00
rootDir = path.Join(os.Getenv("HOME"), DefaultHome)
}
return rootDir
}
2017-04-15 09:07:27 -07:00
//Add debugging flag and execute the root command
func ExecuteWithDebug(RootCmd *cobra.Command) {
var debug bool
2017-04-17 16:59:22 -07:00
RootCmd.SilenceUsage = true
2017-04-15 09:07:27 -07:00
RootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "enables stack trace error messages")
//note that Execute() prints the error if encountered, so no need to reprint the error,
// only if we want the full stack trace
if err := RootCmd.Execute(); err != nil && debug {
cmn.Exit(fmt.Sprintf("%+v\n", err))
}
}
2017-04-17 18:28:03 -07:00
//Quickly registering flags can be quickly achieved through using the utility functions
//RegisterFlags, and RegisterPersistentFlags. Ex:
// flags := []Flag2Register{
// {&myStringFlag, "mystringflag", "foobar", "description of what this flag does"},
// {&myBoolFlag, "myboolflag", false, "description of what this flag does"},
// {&myInt64Flag, "myintflag", 333, "description of what this flag does"},
// }
// RegisterFlags(MyCobraCmd, flags)
type Flag2Register struct {
Pointer interface{}
Use string
Value interface{}
Desc string
}
//register flag utils
func RegisterFlags(c *cobra.Command, flags []Flag2Register) {
registerFlags(c, flags, false)
}
func RegisterPersistentFlags(c *cobra.Command, flags []Flag2Register) {
registerFlags(c, flags, true)
}
func registerFlags(c *cobra.Command, flags []Flag2Register, persistent bool) {
var flagset *pflag.FlagSet
if persistent {
flagset = c.PersistentFlags()
} else {
flagset = c.Flags()
}
for _, f := range flags {
ok := false
switch f.Value.(type) {
case string:
if _, ok = f.Pointer.(*string); ok {
flagset.StringVar(f.Pointer.(*string), f.Use, f.Value.(string), f.Desc)
}
case int:
if _, ok = f.Pointer.(*int); ok {
flagset.IntVar(f.Pointer.(*int), f.Use, f.Value.(int), f.Desc)
}
case uint64:
if _, ok = f.Pointer.(*uint64); ok {
flagset.Uint64Var(f.Pointer.(*uint64), f.Use, f.Value.(uint64), f.Desc)
}
case bool:
if _, ok = f.Pointer.(*bool); ok {
flagset.BoolVar(f.Pointer.(*bool), f.Use, f.Value.(bool), f.Desc)
}
}
if !ok {
panic("improper use of RegisterFlags")
}
}
}
2017-01-29 13:34:48 -08:00
// Returns true for non-empty hex-string prefixed with "0x"
func isHex(s string) bool {
if len(s) > 2 && s[:2] == "0x" {
_, err := hex.DecodeString(s[2:])
if err != nil {
return false
}
return true
}
return false
}
2017-01-30 08:16:00 -08:00
func StripHex(s string) string {
2017-01-29 13:34:48 -08:00
if isHex(s) {
return s[2:]
}
return s
}
func Query(tmAddr string, key []byte) (*abci.ResponseQuery, error) {
2017-03-16 01:01:29 -07:00
uriClient := client.NewURIClient(tmAddr)
2017-01-29 13:34:48 -08:00
tmResult := new(ctypes.TMResult)
params := map[string]interface{}{
"path": "/key",
2017-01-29 18:41:37 -08:00
"data": key,
"prove": true,
2017-01-29 13:34:48 -08:00
}
2017-03-16 01:01:29 -07:00
_, err := uriClient.Call("abci_query", params, tmResult)
2017-01-29 13:34:48 -08:00
if err != nil {
2017-04-15 09:07:27 -07:00
return nil, errors.Errorf("Error calling /abci_query: %v", err)
2017-01-29 13:34:48 -08:00
}
res := (*tmResult).(*ctypes.ResultABCIQuery)
if !res.Response.Code.IsOK() {
2017-04-15 09:07:27 -07:00
return nil, errors.Errorf("Query got non-zero exit code: %v. %s", res.Response.Code, res.Response.Log)
2017-01-29 13:34:48 -08:00
}
2017-01-29 18:41:37 -08:00
return &res.Response, nil
}
// fetch the account by querying the app
func getAcc(tmAddr string, address []byte) (*types.Account, error) {
key := state.AccountKey(address)
response, err := Query(tmAddr, key)
2017-01-29 18:41:37 -08:00
if err != nil {
return nil, err
}
accountBytes := response.Value
2017-01-29 13:34:48 -08:00
if len(accountBytes) == 0 {
2017-04-15 09:07:27 -07:00
return nil, fmt.Errorf("Account bytes are empty for address: %X ", address) //never stack trace
2017-01-29 13:34:48 -08:00
}
2017-01-29 18:41:37 -08:00
2017-01-29 13:34:48 -08:00
var acc *types.Account
err = wire.ReadBinaryBytes(accountBytes, &acc)
if err != nil {
2017-04-15 09:07:27 -07:00
return nil, errors.Errorf("Error reading account %X error: %v",
accountBytes, err.Error())
2017-01-29 13:34:48 -08:00
}
return acc, nil
}
2017-01-29 18:41:37 -08:00
func getHeaderAndCommit(tmAddr string, height int) (*tmtypes.Header, *tmtypes.Commit, error) {
2017-01-29 18:41:37 -08:00
tmResult := new(ctypes.TMResult)
2017-03-16 01:01:29 -07:00
uriClient := client.NewURIClient(tmAddr)
2017-01-29 18:41:37 -08:00
2017-02-16 12:36:46 -08:00
method := "commit"
2017-03-16 01:01:29 -07:00
_, err := uriClient.Call(method, map[string]interface{}{"height": height}, tmResult)
2017-01-29 18:41:37 -08:00
if err != nil {
2017-04-15 09:07:27 -07:00
return nil, nil, errors.Errorf("Error on %s: %v", method, err)
2017-01-29 18:41:37 -08:00
}
2017-02-13 20:22:31 -08:00
resCommit := (*tmResult).(*ctypes.ResultCommit)
2017-02-14 14:31:59 -08:00
header := resCommit.Header
2017-02-13 20:22:31 -08:00
commit := resCommit.Commit
return header, commit, nil
2017-01-29 18:41:37 -08:00
}