Skip to content

Commit

Permalink
client 命令行增加配置文件
Browse files Browse the repository at this point in the history
  • Loading branch information
TokenxyWZY authored and kauchy committed Jan 7, 2019
1 parent ecc17e5 commit ee3a558
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 16 deletions.
159 changes: 159 additions & 0 deletions client/config/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package config

import (
"fmt"
"io/ioutil"
"os"
"path"
"strconv"

"github.com/pelletier/go-toml"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/tendermint/tendermint/libs/cli"
)

const (
flagPrint = "print"
)

var configDefaults map[string]string

func init() {
configDefaults = map[string]string{
"chain_id": "",
"output": "text",
"node": "tcp://localhost:26657",
}
}

func Cmd(defaultCliHome string) *cobra.Command {
cmd := &cobra.Command{
Use: "config <key> [value]",
Short: "Create or query a CLI configuration file",
RunE: runConfigCmd,
Args: cobra.RangeArgs(0, 2),
}

cmd.Flags().String(cli.HomeFlag, defaultCliHome, "set client's home directory for configuration")
cmd.Flags().BoolP(flagPrint, "p", false, "print configuration value or its default if unset")
return cmd
}

func runConfigCmd(cmd *cobra.Command, args []string) error {
cfgFile, err := ensureConfFile(viper.GetString(cli.HomeFlag))
if err != nil {
return err
}

printFlag := viper.GetBool(flagPrint)
if printFlag && len(args) != 1 {
return fmt.Errorf("wrong number of arguments")
}

if !printFlag && len(args) == 1 {
printFlag = true
}

// Load configuration
tree, err := loadConfigFile(cfgFile)
if err != nil {
return err
}

// Print the config and exit
if len(args) == 0 {
s, err := tree.ToTomlString()
if err != nil {
return err
}
fmt.Print(s)
return nil
}

key := args[0]
// Get value action
if printFlag {
switch key {
case "trust_node", "indent":
fmt.Println(tree.GetDefault(key, false).(bool))
default:
if defaultValue, ok := configDefaults[key]; ok {
fmt.Println(tree.GetDefault(key, defaultValue).(string))
} else {
s, _ := tree.Get(key).(string)
fmt.Println(s)
}
}
return nil
}

// Set value action
value := args[1]
switch key {
case "trust_node", "indent":
boolVal, err := strconv.ParseBool(value)
if err != nil {
return err
}
tree.Set(key, boolVal)
default:
tree.Set(key, value)
}

// Save configuration to disk
if err := saveConfigFile(cfgFile, tree); err != nil {
return err
}
fmt.Fprintf(os.Stderr, "configuration saved to %s\n", cfgFile)

return nil
}

func ensureConfFile(rootDir string) (string, error) {
cfgPath := path.Join(rootDir, "config")
if err := os.MkdirAll(cfgPath, os.ModePerm); err != nil {
return "", err
}

return path.Join(cfgPath, "config.toml"), nil
}

func loadConfigFile(cfgFile string) (*toml.Tree, error) {
if _, err := os.Stat(cfgFile); os.IsNotExist(err) {
fmt.Fprintf(os.Stderr, "%s does not exist and create it\n", cfgFile)
t, _ := toml.Load(``)
err := saveConfigFile(cfgFile, t)
if err != nil {
return nil, err
}
return t, nil
}

bz, err := ioutil.ReadFile(cfgFile)
if err != nil {
return nil, err
}

tree, err := toml.LoadBytes(bz)
if err != nil {
return nil, err
}

return tree, nil
}

func saveConfigFile(cfgFile string, tree *toml.Tree) error {
fp, err := os.OpenFile(cfgFile, os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
return err
}
defer fp.Close()

_, err = tree.WriteTo(fp)
return err
}

func errUnknownConfigKey(key string) error {
return fmt.Errorf("unknown configuration key: %q", key)
}
28 changes: 28 additions & 0 deletions client/context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ import (
"encoding/json"
"errors"
"fmt"
"os"
"path"
"regexp"

"github.com/spf13/viper"

"github.com/QOSGroup/qbase/client/types"
go_amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/libs/cli"
cmn "github.com/tendermint/tendermint/libs/common"
rpcclient "github.com/tendermint/tendermint/rpc/client"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
Expand All @@ -33,6 +36,9 @@ type CLIContext struct {
// NewCLIContext returns a new initialized CLIContext with parameters from the
// command line using Viper.
func NewCLIContext() CLIContext {
//优先从$config-home/config.toml文件中加载选项
loadCliConfiguration()

var rpc rpcclient.Client
nodeURI := viper.GetString(types.FlagNode)
if nodeURI != "" {
Expand Down Expand Up @@ -215,3 +221,25 @@ func (ctx CLIContext) PrintResult(obj interface{}) error {
fmt.Println(string(bz))
return nil
}

func loadCliConfiguration() error {

homeDir := viper.GetString(cli.HomeFlag)
cfgFile := path.Join(homeDir, "config", "config.toml")
if _, err := os.Stat(cfgFile); err == nil {
viper.SetConfigFile(cfgFile)

if err := viper.ReadInConfig(); err != nil {
return err
}

//override value
// if tree, err := toml.LoadFile(cfgFile); err == nil {
// for _, k := range tree.Keys() {
// viper.Set(k, tree.Get(k))
// }
// }
}

return nil
}
29 changes: 14 additions & 15 deletions client/tx/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,41 +55,41 @@ func buildAndSignTx(ctx context.CLIContext, txBuilder ITxBuilder) (signedTx type
if err != nil {
return nil, err
}
toChainID := getChainID(ctx)
qcpMode := viper.GetBool(cflags.FlagQcp)
if qcpMode {
return BuildAndSignQcpTx(ctx, itx)
fromChainID := viper.GetString(cflags.FlagQcpFrom)
return BuildAndSignQcpTx(ctx, itx, fromChainID, toChainID)
} else {
return BuildAndSignStdTx(ctx, itx, getChainID(ctx))
return BuildAndSignStdTx(ctx, itx, "", toChainID)
}
}

func BuildAndSignQcpTx(ctx context.CLIContext, tx txs.ITx) (*txs.TxQcp, error) {
func BuildAndSignQcpTx(ctx context.CLIContext, tx txs.ITx, fromChainID, toChainID string) (*txs.TxQcp, error) {

qcpSigner := viper.GetString(cflags.FlagQcpSigner)
qcpFrom := viper.GetString(cflags.FlagQcpFrom)

if qcpSigner == "" || qcpFrom == "" {
if qcpSigner == "" || fromChainID == "" {
return nil, errors.New("in qcp mode, --qcp-from and --qcp-signer flag must set")
}
qcpSignerInfo, err := keys.GetKeyInfo(ctx, qcpSigner)
if err != nil {
return nil, errors.New("query qcp singer info error.")
}

toChainID := getChainID(ctx)
qcpSeq := getQcpInSequence(ctx, qcpFrom)
qcpSeq := getQcpInSequence(ctx, fromChainID)

fmt.Println("> step 1. build and sign TxStd")

txStd, err := BuildAndSignStdTx(ctx, tx, qcpFrom)
txStd, err := BuildAndSignStdTx(ctx, tx, fromChainID, toChainID)
if err != nil {
return nil, err
}

fmt.Println("> step 2. build and sign TxQcp")
_, ok := tx.(*txs.QcpTxResult)

txQcp := txs.NewTxQCP(txStd, qcpFrom,
txQcp := txs.NewTxQCP(txStd, fromChainID,
toChainID,
qcpSeq+1,
viper.GetInt64(cflags.FlagQcpBlockHeight),
Expand All @@ -107,16 +107,15 @@ func BuildAndSignQcpTx(ctx context.CLIContext, tx txs.ITx) (*txs.TxQcp, error) {
return txQcp, nil
}

func BuildAndSignStdTx(ctx context.CLIContext, tx txs.ITx, txStdFromChainID string) (*txs.TxStd, error) {
func BuildAndSignStdTx(ctx context.CLIContext, tx txs.ITx, fromChainID, toChainID string) (*txs.TxStd, error) {

accountNonce := viper.GetInt64(cflags.FlagNonce)
maxGas := viper.GetInt64(cflags.FlagMaxGas)
if maxGas < 0 {
return nil, errors.New("max-gas flag not correct")
}

chainID := getChainID(ctx)
txStd := txs.NewTxStd(tx, chainID, types.NewInt(maxGas))
txStd := txs.NewTxStd(tx, toChainID, types.NewInt(maxGas))

signers := getSigners(ctx, txStd.GetSigners())

Expand All @@ -138,7 +137,7 @@ func BuildAndSignStdTx(ctx context.CLIContext, tx txs.ITx, txStdFromChainID stri
actualNonce = nonce + 1
}

txStd, err = signStdTx(ctx, signerName, actualNonce, txStd, txStdFromChainID)
txStd, err = signStdTx(ctx, signerName, actualNonce, txStd, fromChainID)
if err != nil {
return nil, fmt.Errorf("name %s signStdTx error: %s", signerName, err.Error())
}
Expand All @@ -147,7 +146,7 @@ func BuildAndSignStdTx(ctx context.CLIContext, tx txs.ITx, txStdFromChainID stri
return txStd, nil
}

func signStdTx(ctx context.CLIContext, signerKeyName string, nonce int64, txStd *txs.TxStd, txStdFromChainID string) (*txs.TxStd, error) {
func signStdTx(ctx context.CLIContext, signerKeyName string, nonce int64, txStd *txs.TxStd, fromChainID string) (*txs.TxStd, error) {

info, err := keys.GetKeyInfo(ctx, signerKeyName)
if err != nil {
Expand All @@ -167,7 +166,7 @@ func signStdTx(ctx context.CLIContext, signerKeyName string, nonce int64, txStd
return nil, fmt.Errorf("Name %s is not signer", signerKeyName)
}

sigdata := txStd.BuildSignatureBytes(nonce, txStdFromChainID)
sigdata := txStd.BuildSignatureBytes(nonce, fromChainID)
sig, pubkey := signData(ctx, signerKeyName, sigdata)

txStd.Signature = append(txStd.Signature, txs.Signature{
Expand Down
1 change: 1 addition & 0 deletions client/types/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const (
FlagMaxGas = "max-gas"
FlagJSONIndet = "indent"
FlagNonceNode = "nonce-node"

//qcp flag
FlagQcp = "qcp" //启用QCP模式,发送txQcp消息
FlagQcpSigner = "qcp-signer"
Expand Down
3 changes: 3 additions & 0 deletions example/basecoin/cmd/basecli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
bcli "github.com/QOSGroup/qbase/client"
"github.com/QOSGroup/qbase/client/config"
ctypes "github.com/QOSGroup/qbase/client/types"
"github.com/QOSGroup/qbase/example/basecoin/app"
"github.com/QOSGroup/qbase/example/basecoin/tx/client"
Expand All @@ -27,6 +28,7 @@ func main() {
txCommand.AddCommand(ctypes.PostCommands(client.Commands(cdc)...)...)

rootCmd.AddCommand(
config.Cmd(types.DefaultCLIHome),
txCommand,
bcli.KeysCommand(cdc),
bcli.QueryCommand(cdc),
Expand All @@ -35,6 +37,7 @@ func main() {
)

executor := cli.PrepareBaseCmd(rootCmd, "BC", types.DefaultCLIHome)

err := executor.Execute()
if err != nil {
panic(err)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ require (
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/mitchellh/mapstructure v0.0.0-20180715050151-f15292f7a699 // indirect
github.com/onsi/gomega v1.4.2 // indirect
github.com/pelletier/go-toml v1.2.0 // indirect
github.com/pelletier/go-toml v1.2.0
github.com/pkg/errors v0.8.0
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v0.0.0-20180709125804-ae27198cdd90 // indirect
Expand Down

0 comments on commit ee3a558

Please sign in to comment.