2015-11-02 07:39:53 -08:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2015-11-30 20:56:36 -05:00
|
|
|
"bufio"
|
2016-07-01 20:22:58 -04:00
|
|
|
"encoding/hex"
|
2015-12-21 16:18:41 -08:00
|
|
|
"errors"
|
2015-11-02 07:39:53 -08:00
|
|
|
"fmt"
|
2015-12-01 01:49:54 -05:00
|
|
|
"io"
|
2015-11-02 07:39:53 -08:00
|
|
|
"os"
|
2015-11-30 20:56:36 -05:00
|
|
|
"strings"
|
2015-11-02 07:39:53 -08:00
|
|
|
|
2017-11-30 17:20:36 -05:00
|
|
|
"github.com/spf13/cobra"
|
|
|
|
|
2018-07-01 22:36:49 -04:00
|
|
|
cmn "github.com/tendermint/tendermint/libs/common"
|
|
|
|
"github.com/tendermint/tendermint/libs/log"
|
2017-11-30 17:20:36 -05:00
|
|
|
|
2018-06-22 06:59:02 +02:00
|
|
|
abcicli "github.com/tendermint/tendermint/abci/client"
|
|
|
|
"github.com/tendermint/tendermint/abci/example/code"
|
|
|
|
"github.com/tendermint/tendermint/abci/example/counter"
|
|
|
|
"github.com/tendermint/tendermint/abci/example/kvstore"
|
|
|
|
"github.com/tendermint/tendermint/abci/server"
|
|
|
|
servertest "github.com/tendermint/tendermint/abci/tests/server"
|
|
|
|
"github.com/tendermint/tendermint/abci/types"
|
|
|
|
"github.com/tendermint/tendermint/abci/version"
|
2018-09-29 09:03:19 +09:00
|
|
|
"github.com/tendermint/tendermint/crypto/merkle"
|
2015-11-02 07:39:53 -08:00
|
|
|
)
|
|
|
|
|
2016-05-24 21:51:28 -04:00
|
|
|
// client is a global variable so it can be reused by the console
|
2017-11-30 17:20:36 -05:00
|
|
|
var (
|
|
|
|
client abcicli.Client
|
|
|
|
logger log.Logger
|
|
|
|
)
|
2017-05-01 16:43:52 +04:00
|
|
|
|
2017-10-18 12:48:19 -04:00
|
|
|
// flags
|
|
|
|
var (
|
2017-10-18 15:00:23 -04:00
|
|
|
// global
|
2017-12-01 00:35:14 -05:00
|
|
|
flagAddress string
|
|
|
|
flagAbci string
|
|
|
|
flagVerbose bool // for the println output
|
|
|
|
flagLogLevel string // for the logger
|
2016-12-22 19:00:22 -05:00
|
|
|
|
2017-10-18 15:00:23 -04:00
|
|
|
// query
|
2017-12-01 00:35:14 -05:00
|
|
|
flagPath string
|
|
|
|
flagHeight int
|
|
|
|
flagProve bool
|
2017-10-18 15:00:23 -04:00
|
|
|
|
|
|
|
// counter
|
2017-12-01 00:35:14 -05:00
|
|
|
flagSerial bool
|
2017-10-18 15:00:23 -04:00
|
|
|
|
2018-02-19 20:34:51 +00:00
|
|
|
// kvstore
|
2017-12-01 00:35:14 -05:00
|
|
|
flagPersist string
|
2017-10-18 12:48:19 -04:00
|
|
|
)
|
2016-12-22 19:00:22 -05:00
|
|
|
|
2017-10-18 12:48:19 -04:00
|
|
|
var RootCmd = &cobra.Command{
|
|
|
|
Use: "abci-cli",
|
2018-01-01 16:21:36 +00:00
|
|
|
Short: "the ABCI CLI tool wraps an ABCI client",
|
|
|
|
Long: "the ABCI CLI tool wraps an ABCI client and is used for testing ABCI servers",
|
2017-10-18 12:48:19 -04:00
|
|
|
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
2017-10-18 15:23:39 -04:00
|
|
|
|
|
|
|
switch cmd.Use {
|
2018-12-16 23:34:13 -05:00
|
|
|
case "counter", "kvstore": // for the examples apps, don't pre-run
|
2017-11-08 17:18:42 -05:00
|
|
|
return nil
|
|
|
|
case "version": // skip running for version command
|
2017-10-18 15:23:39 -04:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-10-18 12:48:19 -04:00
|
|
|
if logger == nil {
|
2017-12-01 00:35:14 -05:00
|
|
|
allowLevel, err := log.AllowLevel(flagLogLevel)
|
2017-11-30 17:20:36 -05:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
logger = log.NewFilter(log.NewTMLogger(log.NewSyncWriter(os.Stdout)), allowLevel)
|
2017-10-18 12:48:19 -04:00
|
|
|
}
|
|
|
|
if client == nil {
|
|
|
|
var err error
|
2017-12-01 00:35:14 -05:00
|
|
|
client, err = abcicli.NewClient(flagAddress, flagAbci, false)
|
2017-10-18 12:48:19 -04:00
|
|
|
if err != nil {
|
2017-10-26 08:37:42 -04:00
|
|
|
return err
|
2017-10-18 12:48:19 -04:00
|
|
|
}
|
|
|
|
client.SetLogger(logger.With("module", "abci-client"))
|
2018-01-05 22:19:37 -05:00
|
|
|
if err := client.Start(); err != nil {
|
2017-10-18 12:48:19 -04:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
}
|
2015-11-02 07:39:53 -08:00
|
|
|
|
2017-11-30 17:20:36 -05:00
|
|
|
// Structure for data passed to print response.
|
|
|
|
type response struct {
|
|
|
|
// generic abci response
|
|
|
|
Data []byte
|
|
|
|
Code uint32
|
2017-12-26 15:46:06 -08:00
|
|
|
Info string
|
2017-11-30 17:20:36 -05:00
|
|
|
Log string
|
|
|
|
|
|
|
|
Query *queryResponse
|
|
|
|
}
|
|
|
|
|
|
|
|
type queryResponse struct {
|
|
|
|
Key []byte
|
|
|
|
Value []byte
|
2017-12-01 00:35:14 -05:00
|
|
|
Height int64
|
2018-09-29 09:03:19 +09:00
|
|
|
Proof *merkle.Proof
|
2017-11-30 17:20:36 -05:00
|
|
|
}
|
|
|
|
|
2017-11-27 19:52:06 +00:00
|
|
|
func Execute() error {
|
2017-10-18 12:48:19 -04:00
|
|
|
addGlobalFlags()
|
|
|
|
addCommands()
|
2017-11-27 19:52:06 +00:00
|
|
|
return RootCmd.Execute()
|
2015-11-02 07:39:53 -08:00
|
|
|
}
|
|
|
|
|
2017-10-18 12:48:19 -04:00
|
|
|
func addGlobalFlags() {
|
2018-05-30 21:15:34 -07:00
|
|
|
RootCmd.PersistentFlags().StringVarP(&flagAddress, "address", "", "tcp://0.0.0.0:26658", "address of application socket")
|
2018-01-01 16:21:36 +00:00
|
|
|
RootCmd.PersistentFlags().StringVarP(&flagAbci, "abci", "", "socket", "either socket or grpc")
|
|
|
|
RootCmd.PersistentFlags().BoolVarP(&flagVerbose, "verbose", "v", false, "print the command and results as if it were a console session")
|
|
|
|
RootCmd.PersistentFlags().StringVarP(&flagLogLevel, "log_level", "", "debug", "set the logger level")
|
2017-10-18 12:48:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func addQueryFlags() {
|
2018-01-01 16:21:36 +00:00
|
|
|
queryCmd.PersistentFlags().StringVarP(&flagPath, "path", "", "/store", "path to prefix query with")
|
|
|
|
queryCmd.PersistentFlags().IntVarP(&flagHeight, "height", "", 0, "height to query the blockchain at")
|
|
|
|
queryCmd.PersistentFlags().BoolVarP(&flagProve, "prove", "", false, "whether or not to return a merkle proof of the query result")
|
2017-10-18 12:48:19 -04:00
|
|
|
}
|
|
|
|
|
2017-10-18 15:00:23 -04:00
|
|
|
func addCounterFlags() {
|
2018-01-01 16:21:36 +00:00
|
|
|
counterCmd.PersistentFlags().BoolVarP(&flagSerial, "serial", "", false, "enforce incrementing (serial) transactions")
|
2017-10-18 15:00:23 -04:00
|
|
|
}
|
|
|
|
|
2018-02-19 20:34:51 +00:00
|
|
|
func addKVStoreFlags() {
|
|
|
|
kvstoreCmd.PersistentFlags().StringVarP(&flagPersist, "persist", "", "", "directory to use for a database")
|
|
|
|
}
|
|
|
|
|
2017-10-18 12:48:19 -04:00
|
|
|
func addCommands() {
|
|
|
|
RootCmd.AddCommand(batchCmd)
|
|
|
|
RootCmd.AddCommand(consoleCmd)
|
|
|
|
RootCmd.AddCommand(echoCmd)
|
|
|
|
RootCmd.AddCommand(infoCmd)
|
|
|
|
RootCmd.AddCommand(setOptionCmd)
|
|
|
|
RootCmd.AddCommand(deliverTxCmd)
|
|
|
|
RootCmd.AddCommand(checkTxCmd)
|
|
|
|
RootCmd.AddCommand(commitCmd)
|
2017-11-08 17:18:42 -05:00
|
|
|
RootCmd.AddCommand(versionCmd)
|
2017-05-04 11:29:25 +02:00
|
|
|
RootCmd.AddCommand(testCmd)
|
2017-10-18 12:48:19 -04:00
|
|
|
addQueryFlags()
|
|
|
|
RootCmd.AddCommand(queryCmd)
|
2017-10-18 15:00:23 -04:00
|
|
|
|
|
|
|
// examples
|
|
|
|
addCounterFlags()
|
|
|
|
RootCmd.AddCommand(counterCmd)
|
2018-02-19 20:34:51 +00:00
|
|
|
addKVStoreFlags()
|
|
|
|
RootCmd.AddCommand(kvstoreCmd)
|
2015-11-30 20:56:36 -05:00
|
|
|
}
|
|
|
|
|
2017-10-18 12:48:19 -04:00
|
|
|
var batchCmd = &cobra.Command{
|
|
|
|
Use: "batch",
|
2018-01-01 16:21:36 +00:00
|
|
|
Short: "run a batch of abci commands against an application",
|
|
|
|
Long: `run a batch of abci commands against an application
|
|
|
|
|
|
|
|
This command is run by piping in a file containing a series of commands
|
|
|
|
you'd like to run:
|
|
|
|
|
|
|
|
abci-cli batch < example.file
|
|
|
|
|
|
|
|
where example.file looks something like:
|
|
|
|
|
|
|
|
set_option serial on
|
|
|
|
check_tx 0x00
|
|
|
|
check_tx 0xff
|
|
|
|
deliver_tx 0x00
|
|
|
|
check_tx 0x00
|
|
|
|
deliver_tx 0x01
|
|
|
|
deliver_tx 0x04
|
|
|
|
info
|
|
|
|
`,
|
|
|
|
Args: cobra.ExactArgs(0),
|
2019-07-30 16:13:35 +02:00
|
|
|
RunE: cmdBatch,
|
2016-09-12 10:21:20 +02:00
|
|
|
}
|
|
|
|
|
2017-10-18 12:48:19 -04:00
|
|
|
var consoleCmd = &cobra.Command{
|
2018-01-01 16:21:36 +00:00
|
|
|
Use: "console",
|
|
|
|
Short: "start an interactive ABCI console for multiple commands",
|
|
|
|
Long: `start an interactive ABCI console for multiple commands
|
2018-01-05 22:19:37 -05:00
|
|
|
|
2018-01-01 16:21:36 +00:00
|
|
|
This command opens an interactive console for running any of the other commands
|
|
|
|
without opening a new connection each time
|
|
|
|
`,
|
2017-10-26 08:51:43 -04:00
|
|
|
Args: cobra.ExactArgs(0),
|
2017-12-20 15:41:28 -05:00
|
|
|
ValidArgs: []string{"echo", "info", "set_option", "deliver_tx", "check_tx", "commit", "query"},
|
2019-07-30 16:13:35 +02:00
|
|
|
RunE: cmdConsole,
|
2017-10-18 12:48:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
var echoCmd = &cobra.Command{
|
|
|
|
Use: "echo",
|
2018-01-01 16:21:36 +00:00
|
|
|
Short: "have the application echo a message",
|
|
|
|
Long: "have the application echo a message",
|
2017-10-26 08:51:43 -04:00
|
|
|
Args: cobra.ExactArgs(1),
|
2019-07-30 16:13:35 +02:00
|
|
|
RunE: cmdEcho,
|
2017-10-18 12:48:19 -04:00
|
|
|
}
|
|
|
|
var infoCmd = &cobra.Command{
|
|
|
|
Use: "info",
|
2018-01-01 16:21:36 +00:00
|
|
|
Short: "get some info about the application",
|
|
|
|
Long: "get some info about the application",
|
2017-10-26 08:51:43 -04:00
|
|
|
Args: cobra.ExactArgs(0),
|
2019-07-30 16:13:35 +02:00
|
|
|
RunE: cmdInfo,
|
2017-10-18 12:48:19 -04:00
|
|
|
}
|
|
|
|
var setOptionCmd = &cobra.Command{
|
|
|
|
Use: "set_option",
|
2018-01-01 16:21:36 +00:00
|
|
|
Short: "set an option on the application",
|
|
|
|
Long: "set an option on the application",
|
2017-10-26 08:51:43 -04:00
|
|
|
Args: cobra.ExactArgs(2),
|
2019-07-30 16:13:35 +02:00
|
|
|
RunE: cmdSetOption,
|
2017-10-18 12:48:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
var deliverTxCmd = &cobra.Command{
|
|
|
|
Use: "deliver_tx",
|
2018-01-01 16:21:36 +00:00
|
|
|
Short: "deliver a new transaction to the application",
|
|
|
|
Long: "deliver a new transaction to the application",
|
2017-10-26 08:51:43 -04:00
|
|
|
Args: cobra.ExactArgs(1),
|
2019-07-30 16:13:35 +02:00
|
|
|
RunE: cmdDeliverTx,
|
2017-10-18 12:48:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
var checkTxCmd = &cobra.Command{
|
|
|
|
Use: "check_tx",
|
2018-01-01 16:21:36 +00:00
|
|
|
Short: "validate a transaction",
|
|
|
|
Long: "validate a transaction",
|
2017-10-26 08:51:43 -04:00
|
|
|
Args: cobra.ExactArgs(1),
|
2019-07-30 16:13:35 +02:00
|
|
|
RunE: cmdCheckTx,
|
2017-10-18 12:48:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
var commitCmd = &cobra.Command{
|
|
|
|
Use: "commit",
|
2018-01-01 16:21:36 +00:00
|
|
|
Short: "commit the application state and return the Merkle root hash",
|
|
|
|
Long: "commit the application state and return the Merkle root hash",
|
2017-10-26 08:51:43 -04:00
|
|
|
Args: cobra.ExactArgs(0),
|
2019-07-30 16:13:35 +02:00
|
|
|
RunE: cmdCommit,
|
2017-10-18 12:48:19 -04:00
|
|
|
}
|
|
|
|
|
2017-11-08 17:18:42 -05:00
|
|
|
var versionCmd = &cobra.Command{
|
|
|
|
Use: "version",
|
2018-01-01 16:21:36 +00:00
|
|
|
Short: "print ABCI console version",
|
|
|
|
Long: "print ABCI console version",
|
2017-11-08 17:18:42 -05:00
|
|
|
Args: cobra.ExactArgs(0),
|
|
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
|
|
fmt.Println(version.Version)
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2017-10-18 12:48:19 -04:00
|
|
|
var queryCmd = &cobra.Command{
|
|
|
|
Use: "query",
|
2018-01-01 16:21:36 +00:00
|
|
|
Short: "query the application state",
|
|
|
|
Long: "query the application state",
|
2017-10-26 08:51:43 -04:00
|
|
|
Args: cobra.ExactArgs(1),
|
2019-07-30 16:13:35 +02:00
|
|
|
RunE: cmdQuery,
|
2017-10-18 12:48:19 -04:00
|
|
|
}
|
|
|
|
|
2017-10-18 15:00:23 -04:00
|
|
|
var counterCmd = &cobra.Command{
|
|
|
|
Use: "counter",
|
|
|
|
Short: "ABCI demo example",
|
2018-01-01 16:21:36 +00:00
|
|
|
Long: "ABCI demo example",
|
2017-10-26 08:51:43 -04:00
|
|
|
Args: cobra.ExactArgs(0),
|
2019-07-30 16:13:35 +02:00
|
|
|
RunE: cmdCounter,
|
2017-10-18 15:00:23 -04:00
|
|
|
}
|
|
|
|
|
2018-02-19 20:34:51 +00:00
|
|
|
var kvstoreCmd = &cobra.Command{
|
|
|
|
Use: "kvstore",
|
2017-10-18 15:00:23 -04:00
|
|
|
Short: "ABCI demo example",
|
2018-01-01 16:21:36 +00:00
|
|
|
Long: "ABCI demo example",
|
2017-10-26 08:51:43 -04:00
|
|
|
Args: cobra.ExactArgs(0),
|
2019-07-30 16:13:35 +02:00
|
|
|
RunE: cmdKVStore,
|
2017-10-18 15:00:23 -04:00
|
|
|
}
|
|
|
|
|
2017-05-04 11:29:25 +02:00
|
|
|
var testCmd = &cobra.Command{
|
2017-10-20 18:44:37 +02:00
|
|
|
Use: "test",
|
2018-01-01 16:21:36 +00:00
|
|
|
Short: "run integration tests",
|
|
|
|
Long: "run integration tests",
|
2017-10-20 18:44:37 +02:00
|
|
|
Args: cobra.ExactArgs(0),
|
2019-07-30 16:13:35 +02:00
|
|
|
RunE: cmdTest,
|
2017-05-04 11:29:25 +02:00
|
|
|
}
|
|
|
|
|
2017-10-18 12:48:19 -04:00
|
|
|
// Generates new Args array based off of previous call args to maintain flag persistence
|
2017-01-12 01:03:51 -05:00
|
|
|
func persistentArgs(line []byte) []string {
|
|
|
|
|
2017-09-21 15:26:43 -04:00
|
|
|
// generate the arguments to run from original os.Args
|
2017-01-12 01:03:51 -05:00
|
|
|
// to maintain flag arguments
|
|
|
|
args := os.Args
|
|
|
|
args = args[:len(args)-1] // remove the previous command argument
|
|
|
|
|
2017-09-21 15:26:43 -04:00
|
|
|
if len(line) > 0 { // prevents introduction of extra space leading to argument parse errors
|
2017-01-12 01:03:51 -05:00
|
|
|
args = append(args, strings.Split(string(line), " ")...)
|
|
|
|
}
|
|
|
|
return args
|
|
|
|
}
|
|
|
|
|
2015-11-02 07:39:53 -08:00
|
|
|
//--------------------------------------------------------------------------------
|
|
|
|
|
2017-12-12 21:06:56 +01:00
|
|
|
func compose(fs []func() error) error {
|
|
|
|
if len(fs) == 0 {
|
|
|
|
return nil
|
2017-10-20 18:44:37 +02:00
|
|
|
} else {
|
2017-12-12 21:06:56 +01:00
|
|
|
err := fs[0]()
|
|
|
|
if err == nil {
|
|
|
|
return compose(fs[1:])
|
|
|
|
} else {
|
|
|
|
return err
|
|
|
|
}
|
2017-10-20 18:44:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-04 11:29:25 +02:00
|
|
|
func cmdTest(cmd *cobra.Command, args []string) error {
|
2017-12-12 21:06:56 +01:00
|
|
|
return compose(
|
|
|
|
[]func() error{
|
|
|
|
func() error { return servertest.InitChain(client) },
|
|
|
|
func() error { return servertest.SetOption(client, "serial", "on") },
|
|
|
|
func() error { return servertest.Commit(client, nil) },
|
|
|
|
func() error { return servertest.DeliverTx(client, []byte("abc"), code.CodeTypeBadNonce, nil) },
|
|
|
|
func() error { return servertest.Commit(client, nil) },
|
|
|
|
func() error { return servertest.DeliverTx(client, []byte{0x00}, code.CodeTypeOK, nil) },
|
|
|
|
func() error { return servertest.Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 1}) },
|
|
|
|
func() error { return servertest.DeliverTx(client, []byte{0x00}, code.CodeTypeBadNonce, nil) },
|
|
|
|
func() error { return servertest.DeliverTx(client, []byte{0x01}, code.CodeTypeOK, nil) },
|
|
|
|
func() error { return servertest.DeliverTx(client, []byte{0x00, 0x02}, code.CodeTypeOK, nil) },
|
|
|
|
func() error { return servertest.DeliverTx(client, []byte{0x00, 0x03}, code.CodeTypeOK, nil) },
|
|
|
|
func() error { return servertest.DeliverTx(client, []byte{0x00, 0x00, 0x04}, code.CodeTypeOK, nil) },
|
2018-01-01 16:21:36 +00:00
|
|
|
func() error {
|
|
|
|
return servertest.DeliverTx(client, []byte{0x00, 0x00, 0x06}, code.CodeTypeBadNonce, nil)
|
|
|
|
},
|
|
|
|
func() error { return servertest.Commit(client, []byte{0, 0, 0, 0, 0, 0, 0, 5}) },
|
2017-12-12 21:06:56 +01:00
|
|
|
})
|
2017-05-04 11:29:25 +02:00
|
|
|
}
|
|
|
|
|
2017-10-26 08:37:42 -04:00
|
|
|
func cmdBatch(cmd *cobra.Command, args []string) error {
|
2015-12-01 01:49:54 -05:00
|
|
|
bufReader := bufio.NewReader(os.Stdin)
|
2019-08-02 08:53:52 +02:00
|
|
|
LOOP:
|
2015-12-01 01:49:54 -05:00
|
|
|
for {
|
2017-12-09 19:48:29 -07:00
|
|
|
|
2015-12-01 01:49:54 -05:00
|
|
|
line, more, err := bufReader.ReadLine()
|
2019-08-02 08:53:52 +02:00
|
|
|
switch {
|
|
|
|
case more:
|
2017-10-26 08:37:42 -04:00
|
|
|
return errors.New("Input line is too long")
|
2019-08-02 08:53:52 +02:00
|
|
|
case err == io.EOF:
|
|
|
|
break LOOP
|
|
|
|
case len(line) == 0:
|
2015-12-14 18:00:18 -05:00
|
|
|
continue
|
2019-08-02 08:53:52 +02:00
|
|
|
case err != nil:
|
2017-10-26 08:37:42 -04:00
|
|
|
return err
|
2015-12-01 01:49:54 -05:00
|
|
|
}
|
2017-12-10 21:39:30 +00:00
|
|
|
|
2017-12-12 00:55:07 -07:00
|
|
|
cmdArgs := persistentArgs(line)
|
|
|
|
if err := muxOnCommands(cmd, cmdArgs); err != nil {
|
2017-12-10 21:39:30 +00:00
|
|
|
return err
|
|
|
|
}
|
2017-12-12 00:55:07 -07:00
|
|
|
fmt.Println()
|
2015-12-01 01:49:54 -05:00
|
|
|
}
|
2017-10-26 08:37:42 -04:00
|
|
|
return nil
|
2015-12-01 01:49:54 -05:00
|
|
|
}
|
|
|
|
|
2017-10-26 08:37:42 -04:00
|
|
|
func cmdConsole(cmd *cobra.Command, args []string) error {
|
2015-11-30 20:56:36 -05:00
|
|
|
for {
|
2017-10-23 19:35:02 -04:00
|
|
|
fmt.Printf("> ")
|
2015-11-30 20:56:36 -05:00
|
|
|
bufReader := bufio.NewReader(os.Stdin)
|
|
|
|
line, more, err := bufReader.ReadLine()
|
|
|
|
if more {
|
2017-10-26 08:37:42 -04:00
|
|
|
return errors.New("Input is too long")
|
2015-11-30 20:56:36 -05:00
|
|
|
} else if err != nil {
|
2017-10-26 08:37:42 -04:00
|
|
|
return err
|
2015-11-30 20:56:36 -05:00
|
|
|
}
|
|
|
|
|
2017-10-18 12:48:19 -04:00
|
|
|
pArgs := persistentArgs(line)
|
2017-12-09 19:48:29 -07:00
|
|
|
if err := muxOnCommands(cmd, pArgs); err != nil {
|
2017-10-26 08:37:42 -04:00
|
|
|
return err
|
2017-10-18 12:48:19 -04:00
|
|
|
}
|
2015-11-30 20:56:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-09 19:48:29 -07:00
|
|
|
func muxOnCommands(cmd *cobra.Command, pArgs []string) error {
|
2017-12-12 00:55:07 -07:00
|
|
|
if len(pArgs) < 2 {
|
2017-12-16 15:49:35 -07:00
|
|
|
return errors.New("expecting persistent args of the form: abci-cli [command] <...>")
|
2017-12-09 19:48:29 -07:00
|
|
|
}
|
2017-12-20 15:41:28 -05:00
|
|
|
|
|
|
|
// TODO: this parsing is fragile
|
|
|
|
args := []string{}
|
|
|
|
for i := 0; i < len(pArgs); i++ {
|
|
|
|
arg := pArgs[i]
|
|
|
|
|
|
|
|
// check for flags
|
|
|
|
if strings.HasPrefix(arg, "-") {
|
|
|
|
// if it has an equal, we can just skip
|
|
|
|
if strings.Contains(arg, "=") {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// if its a boolean, we can just skip
|
|
|
|
_, err := cmd.Flags().GetBool(strings.TrimLeft(arg, "-"))
|
|
|
|
if err == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// otherwise, we need to skip the next one too
|
2019-07-30 16:13:35 +02:00
|
|
|
i++
|
2017-12-20 15:41:28 -05:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// append the actual arg
|
|
|
|
args = append(args, arg)
|
|
|
|
}
|
|
|
|
var subCommand string
|
|
|
|
var actualArgs []string
|
|
|
|
if len(args) > 1 {
|
|
|
|
subCommand = args[1]
|
|
|
|
}
|
|
|
|
if len(args) > 2 {
|
|
|
|
actualArgs = args[2:]
|
|
|
|
}
|
|
|
|
cmd.Use = subCommand // for later print statements ...
|
2017-12-10 21:39:30 +00:00
|
|
|
|
2017-12-09 19:48:29 -07:00
|
|
|
switch strings.ToLower(subCommand) {
|
|
|
|
case "check_tx":
|
|
|
|
return cmdCheckTx(cmd, actualArgs)
|
|
|
|
case "commit":
|
|
|
|
return cmdCommit(cmd, actualArgs)
|
|
|
|
case "deliver_tx":
|
|
|
|
return cmdDeliverTx(cmd, actualArgs)
|
|
|
|
case "echo":
|
|
|
|
return cmdEcho(cmd, actualArgs)
|
|
|
|
case "info":
|
|
|
|
return cmdInfo(cmd, actualArgs)
|
|
|
|
case "query":
|
|
|
|
return cmdQuery(cmd, actualArgs)
|
|
|
|
case "set_option":
|
|
|
|
return cmdSetOption(cmd, actualArgs)
|
|
|
|
default:
|
|
|
|
return cmdUnimplemented(cmd, pArgs)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func cmdUnimplemented(cmd *cobra.Command, args []string) error {
|
|
|
|
msg := "unimplemented command"
|
2018-08-15 16:28:17 +08:00
|
|
|
|
2017-12-12 00:55:07 -07:00
|
|
|
if len(args) > 0 {
|
|
|
|
msg += fmt.Sprintf(" args: [%s]", strings.Join(args, " "))
|
|
|
|
}
|
2017-12-09 19:48:29 -07:00
|
|
|
printResponse(cmd, args, response{
|
|
|
|
Code: codeBad,
|
|
|
|
Log: msg,
|
|
|
|
})
|
2018-08-15 16:28:17 +08:00
|
|
|
|
|
|
|
fmt.Println("Available commands:")
|
|
|
|
fmt.Printf("%s: %s\n", echoCmd.Use, echoCmd.Short)
|
|
|
|
fmt.Printf("%s: %s\n", infoCmd.Use, infoCmd.Short)
|
|
|
|
fmt.Printf("%s: %s\n", checkTxCmd.Use, checkTxCmd.Short)
|
|
|
|
fmt.Printf("%s: %s\n", deliverTxCmd.Use, deliverTxCmd.Short)
|
|
|
|
fmt.Printf("%s: %s\n", queryCmd.Use, queryCmd.Short)
|
|
|
|
fmt.Printf("%s: %s\n", commitCmd.Use, commitCmd.Short)
|
|
|
|
fmt.Printf("%s: %s\n", setOptionCmd.Use, setOptionCmd.Short)
|
|
|
|
fmt.Println("Use \"[command] --help\" for more information about a command.")
|
|
|
|
|
2017-12-09 19:48:29 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-12-06 18:18:13 -05:00
|
|
|
// Have the application echo a message
|
2017-10-26 08:37:42 -04:00
|
|
|
func cmdEcho(cmd *cobra.Command, args []string) error {
|
2017-12-09 19:48:29 -07:00
|
|
|
msg := ""
|
|
|
|
if len(args) > 0 {
|
|
|
|
msg = args[0]
|
|
|
|
}
|
|
|
|
res, err := client.EchoSync(msg)
|
2017-11-21 17:33:34 -06:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-10-18 12:48:19 -04:00
|
|
|
printResponse(cmd, args, response{
|
2017-11-21 17:33:34 -06:00
|
|
|
Data: []byte(res.Message),
|
2017-01-23 23:42:09 -08:00
|
|
|
})
|
2017-10-26 08:37:42 -04:00
|
|
|
return nil
|
2015-12-06 18:18:13 -05:00
|
|
|
}
|
|
|
|
|
2015-11-30 23:49:18 -05:00
|
|
|
// Get some info from the application
|
2017-10-26 08:37:42 -04:00
|
|
|
func cmdInfo(cmd *cobra.Command, args []string) error {
|
2017-09-22 11:10:39 -04:00
|
|
|
var version string
|
|
|
|
if len(args) == 1 {
|
|
|
|
version = args[0]
|
|
|
|
}
|
2018-07-27 06:23:19 +04:00
|
|
|
res, err := client.InfoSync(types.RequestInfo{Version: version})
|
2016-12-26 17:44:36 -08:00
|
|
|
if err != nil {
|
2017-10-26 08:37:42 -04:00
|
|
|
return err
|
2016-12-26 17:44:36 -08:00
|
|
|
}
|
2017-10-18 12:48:19 -04:00
|
|
|
printResponse(cmd, args, response{
|
2017-11-21 17:33:34 -06:00
|
|
|
Data: []byte(res.Data),
|
2017-01-23 23:42:09 -08:00
|
|
|
})
|
2017-10-26 08:37:42 -04:00
|
|
|
return nil
|
2015-11-30 23:49:18 -05:00
|
|
|
}
|
|
|
|
|
2017-12-09 19:48:29 -07:00
|
|
|
const codeBad uint32 = 10
|
|
|
|
|
2015-11-30 23:49:18 -05:00
|
|
|
// Set an option on the application
|
2017-10-26 08:37:42 -04:00
|
|
|
func cmdSetOption(cmd *cobra.Command, args []string) error {
|
2017-12-09 19:48:29 -07:00
|
|
|
if len(args) < 2 {
|
|
|
|
printResponse(cmd, args, response{
|
|
|
|
Code: codeBad,
|
|
|
|
Log: "want at least arguments of the form: <key> <value>",
|
|
|
|
})
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-11-27 19:04:21 +00:00
|
|
|
key, val := args[0], args[1]
|
2018-07-27 06:23:19 +04:00
|
|
|
_, err := client.SetOptionSync(types.RequestSetOption{Key: key, Value: val})
|
2017-11-21 17:33:34 -06:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-12-26 15:46:06 -08:00
|
|
|
printResponse(cmd, args, response{Log: "OK (SetOption doesn't return anything.)"}) // NOTE: Nothing to show...
|
2017-10-26 08:37:42 -04:00
|
|
|
return nil
|
2015-11-30 23:49:18 -05:00
|
|
|
}
|
|
|
|
|
2015-11-02 07:39:53 -08:00
|
|
|
// Append a new tx to application
|
2017-10-26 08:37:42 -04:00
|
|
|
func cmdDeliverTx(cmd *cobra.Command, args []string) error {
|
2017-12-09 19:48:29 -07:00
|
|
|
if len(args) == 0 {
|
|
|
|
printResponse(cmd, args, response{
|
|
|
|
Code: codeBad,
|
|
|
|
Log: "want the tx",
|
|
|
|
})
|
|
|
|
return nil
|
|
|
|
}
|
2017-10-18 12:48:19 -04:00
|
|
|
txBytes, err := stringOrHexToBytes(args[0])
|
2017-01-02 18:49:10 -08:00
|
|
|
if err != nil {
|
2017-10-26 08:37:42 -04:00
|
|
|
return err
|
2017-01-02 18:49:10 -08:00
|
|
|
}
|
abci: Refactor CheckTx to notify of recheck (#3744)
As per #2127, this refactors the RequestCheckTx ProtoBuf struct to allow for a flag indicating whether a query is a recheck or not (and allows for possible future, more nuanced states).
In order to pass this extended information through to the ABCI app, the proxy.AppConnMempool (and, for consistency, the proxy.AppConnConsensus) interface seems to need to be refactored along with abcicli.Client.
And, as per this comment, I've made the following modification to the protobuf definition for the RequestCheckTx structure:
enum CheckTxType {
New = 0;
Recheck = 1;
}
message RequestCheckTx {
bytes tx = 1;
CheckTxType type = 2;
}
* Refactor ABCI CheckTx to notify of recheck
As per #2127, this refactors the `RequestCheckTx` ProtoBuf struct to allow for:
1. a flag indicating whether a query is a recheck or not (and allows for
possible future, more nuanced states)
2. an `additional_data` bytes array to provide information for those more
nuanced states.
In order to pass this extended information through to the ABCI app, the
`proxy.AppConnMempool` (and, for consistency, the
`proxy.AppConnConsensus`) interface seems to need to be refactored.
Commits:
* Fix linting issue
* Add CHANGELOG_PENDING entry
* Remove extraneous explicit initialization
* Update ABCI spec doc to include new CheckTx params
* Rename method param for consistency
* Rename CheckTxType enum values and remove additional_data param
2019-07-02 10:14:53 -04:00
|
|
|
res, err := client.DeliverTxSync(types.RequestDeliverTx{Tx: txBytes})
|
2017-11-22 17:34:00 -06:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-10-18 12:48:19 -04:00
|
|
|
printResponse(cmd, args, response{
|
2017-01-23 23:42:09 -08:00
|
|
|
Code: res.Code,
|
|
|
|
Data: res.Data,
|
2017-12-26 15:46:06 -08:00
|
|
|
Info: res.Info,
|
2017-01-23 23:42:09 -08:00
|
|
|
Log: res.Log,
|
|
|
|
})
|
2017-10-26 08:37:42 -04:00
|
|
|
return nil
|
2015-11-02 07:39:53 -08:00
|
|
|
}
|
|
|
|
|
2016-01-08 16:52:02 -08:00
|
|
|
// Validate a tx
|
2017-10-26 08:37:42 -04:00
|
|
|
func cmdCheckTx(cmd *cobra.Command, args []string) error {
|
2017-12-09 19:48:29 -07:00
|
|
|
if len(args) == 0 {
|
|
|
|
printResponse(cmd, args, response{
|
|
|
|
Code: codeBad,
|
2017-12-26 15:46:06 -08:00
|
|
|
Info: "want the tx",
|
2017-12-09 19:48:29 -07:00
|
|
|
})
|
|
|
|
return nil
|
|
|
|
}
|
2017-10-18 12:48:19 -04:00
|
|
|
txBytes, err := stringOrHexToBytes(args[0])
|
2017-01-02 18:49:10 -08:00
|
|
|
if err != nil {
|
2017-10-26 08:37:42 -04:00
|
|
|
return err
|
2017-01-02 18:49:10 -08:00
|
|
|
}
|
abci: Refactor CheckTx to notify of recheck (#3744)
As per #2127, this refactors the RequestCheckTx ProtoBuf struct to allow for a flag indicating whether a query is a recheck or not (and allows for possible future, more nuanced states).
In order to pass this extended information through to the ABCI app, the proxy.AppConnMempool (and, for consistency, the proxy.AppConnConsensus) interface seems to need to be refactored along with abcicli.Client.
And, as per this comment, I've made the following modification to the protobuf definition for the RequestCheckTx structure:
enum CheckTxType {
New = 0;
Recheck = 1;
}
message RequestCheckTx {
bytes tx = 1;
CheckTxType type = 2;
}
* Refactor ABCI CheckTx to notify of recheck
As per #2127, this refactors the `RequestCheckTx` ProtoBuf struct to allow for:
1. a flag indicating whether a query is a recheck or not (and allows for
possible future, more nuanced states)
2. an `additional_data` bytes array to provide information for those more
nuanced states.
In order to pass this extended information through to the ABCI app, the
`proxy.AppConnMempool` (and, for consistency, the
`proxy.AppConnConsensus`) interface seems to need to be refactored.
Commits:
* Fix linting issue
* Add CHANGELOG_PENDING entry
* Remove extraneous explicit initialization
* Update ABCI spec doc to include new CheckTx params
* Rename method param for consistency
* Rename CheckTxType enum values and remove additional_data param
2019-07-02 10:14:53 -04:00
|
|
|
res, err := client.CheckTxSync(types.RequestCheckTx{Tx: txBytes})
|
2017-11-22 17:34:00 -06:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-10-18 12:48:19 -04:00
|
|
|
printResponse(cmd, args, response{
|
2017-01-23 23:42:09 -08:00
|
|
|
Code: res.Code,
|
|
|
|
Data: res.Data,
|
2017-12-26 15:46:06 -08:00
|
|
|
Info: res.Info,
|
2017-01-23 23:42:09 -08:00
|
|
|
Log: res.Log,
|
|
|
|
})
|
2017-10-26 08:37:42 -04:00
|
|
|
return nil
|
2015-11-02 07:39:53 -08:00
|
|
|
}
|
|
|
|
|
2016-01-08 16:52:02 -08:00
|
|
|
// Get application Merkle root hash
|
2017-10-26 08:37:42 -04:00
|
|
|
func cmdCommit(cmd *cobra.Command, args []string) error {
|
2017-11-22 17:34:00 -06:00
|
|
|
res, err := client.CommitSync()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-10-18 12:48:19 -04:00
|
|
|
printResponse(cmd, args, response{
|
2017-01-23 23:42:09 -08:00
|
|
|
Data: res.Data,
|
|
|
|
})
|
2017-10-26 08:37:42 -04:00
|
|
|
return nil
|
2015-11-02 07:39:53 -08:00
|
|
|
}
|
|
|
|
|
2016-01-22 15:50:11 -08:00
|
|
|
// Query application state
|
2017-10-26 08:37:42 -04:00
|
|
|
func cmdQuery(cmd *cobra.Command, args []string) error {
|
2017-12-09 19:48:29 -07:00
|
|
|
if len(args) == 0 {
|
|
|
|
printResponse(cmd, args, response{
|
|
|
|
Code: codeBad,
|
2017-12-26 15:46:06 -08:00
|
|
|
Info: "want the query",
|
|
|
|
Log: "",
|
2017-12-09 19:48:29 -07:00
|
|
|
})
|
|
|
|
return nil
|
|
|
|
}
|
2017-05-13 18:37:00 +02:00
|
|
|
queryBytes, err := stringOrHexToBytes(args[0])
|
2017-01-02 18:49:10 -08:00
|
|
|
if err != nil {
|
2017-10-26 08:37:42 -04:00
|
|
|
return err
|
2017-01-02 18:49:10 -08:00
|
|
|
}
|
2017-05-13 18:37:00 +02:00
|
|
|
|
2017-01-23 23:42:09 -08:00
|
|
|
resQuery, err := client.QuerySync(types.RequestQuery{
|
2017-02-14 16:53:21 -05:00
|
|
|
Data: queryBytes,
|
2017-12-01 00:35:14 -05:00
|
|
|
Path: flagPath,
|
|
|
|
Height: int64(flagHeight),
|
|
|
|
Prove: flagProve,
|
2017-01-23 23:42:09 -08:00
|
|
|
})
|
2017-01-10 17:06:51 +01:00
|
|
|
if err != nil {
|
2017-10-26 08:37:42 -04:00
|
|
|
return err
|
2017-01-10 15:49:26 +01:00
|
|
|
}
|
2017-10-18 12:48:19 -04:00
|
|
|
printResponse(cmd, args, response{
|
2017-03-03 18:39:10 -05:00
|
|
|
Code: resQuery.Code,
|
2017-12-26 15:46:06 -08:00
|
|
|
Info: resQuery.Info,
|
2017-03-03 18:39:10 -05:00
|
|
|
Log: resQuery.Log,
|
|
|
|
Query: &queryResponse{
|
|
|
|
Key: resQuery.Key,
|
|
|
|
Value: resQuery.Value,
|
|
|
|
Height: resQuery.Height,
|
|
|
|
Proof: resQuery.Proof,
|
|
|
|
},
|
2017-01-23 23:42:09 -08:00
|
|
|
})
|
2017-10-26 08:37:42 -04:00
|
|
|
return nil
|
2016-01-22 15:50:11 -08:00
|
|
|
}
|
|
|
|
|
2017-10-26 08:37:42 -04:00
|
|
|
func cmdCounter(cmd *cobra.Command, args []string) error {
|
2017-12-01 00:35:14 -05:00
|
|
|
app := counter.NewCounterApplication(flagSerial)
|
2017-10-18 15:00:23 -04:00
|
|
|
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
|
|
|
|
|
|
|
|
// Start the listener
|
2018-05-16 16:25:28 +09:00
|
|
|
srv, err := server.NewServer(flagAddress, flagAbci, app)
|
2017-10-18 15:00:23 -04:00
|
|
|
if err != nil {
|
2017-10-26 08:37:42 -04:00
|
|
|
return err
|
2017-10-18 15:00:23 -04:00
|
|
|
}
|
|
|
|
srv.SetLogger(logger.With("module", "abci-server"))
|
2018-01-05 22:19:37 -05:00
|
|
|
if err := srv.Start(); err != nil {
|
2017-10-26 08:37:42 -04:00
|
|
|
return err
|
2017-10-18 15:00:23 -04:00
|
|
|
}
|
|
|
|
|
2019-02-23 19:48:28 +04:00
|
|
|
// Stop upon receiving SIGTERM or CTRL-C.
|
|
|
|
cmn.TrapSignal(logger, func() {
|
2017-10-18 15:00:23 -04:00
|
|
|
// Cleanup
|
|
|
|
srv.Stop()
|
|
|
|
})
|
2019-02-23 19:48:28 +04:00
|
|
|
|
|
|
|
// Run forever.
|
|
|
|
select {}
|
2017-10-18 15:00:23 -04:00
|
|
|
}
|
|
|
|
|
2018-02-19 20:34:51 +00:00
|
|
|
func cmdKVStore(cmd *cobra.Command, args []string) error {
|
2017-10-18 15:00:23 -04:00
|
|
|
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
|
|
|
|
|
|
|
|
// Create the application - in memory or persisted to disk
|
|
|
|
var app types.Application
|
2017-12-01 00:35:14 -05:00
|
|
|
if flagPersist == "" {
|
2018-02-19 20:39:36 +00:00
|
|
|
app = kvstore.NewKVStoreApplication()
|
2017-10-18 15:00:23 -04:00
|
|
|
} else {
|
2018-02-19 20:39:36 +00:00
|
|
|
app = kvstore.NewPersistentKVStoreApplication(flagPersist)
|
|
|
|
app.(*kvstore.PersistentKVStoreApplication).SetLogger(logger.With("module", "kvstore"))
|
2017-10-18 15:00:23 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Start the listener
|
2018-05-16 16:25:28 +09:00
|
|
|
srv, err := server.NewServer(flagAddress, flagAbci, app)
|
2017-10-18 15:00:23 -04:00
|
|
|
if err != nil {
|
2017-10-26 08:37:42 -04:00
|
|
|
return err
|
2017-10-18 15:00:23 -04:00
|
|
|
}
|
|
|
|
srv.SetLogger(logger.With("module", "abci-server"))
|
2018-01-05 22:19:37 -05:00
|
|
|
if err := srv.Start(); err != nil {
|
2017-10-26 08:37:42 -04:00
|
|
|
return err
|
2017-10-18 15:00:23 -04:00
|
|
|
}
|
|
|
|
|
2019-02-23 19:48:28 +04:00
|
|
|
// Stop upon receiving SIGTERM or CTRL-C.
|
|
|
|
cmn.TrapSignal(logger, func() {
|
2017-10-18 15:00:23 -04:00
|
|
|
// Cleanup
|
|
|
|
srv.Stop()
|
|
|
|
})
|
2019-02-23 19:48:28 +04:00
|
|
|
|
|
|
|
// Run forever.
|
|
|
|
select {}
|
2017-10-18 15:00:23 -04:00
|
|
|
}
|
|
|
|
|
2015-11-02 07:39:53 -08:00
|
|
|
//--------------------------------------------------------------------------------
|
|
|
|
|
2017-10-18 12:48:19 -04:00
|
|
|
func printResponse(cmd *cobra.Command, args []string, rsp response) {
|
2017-01-12 01:03:51 -05:00
|
|
|
|
2017-12-01 00:35:14 -05:00
|
|
|
if flagVerbose {
|
2017-10-18 12:48:19 -04:00
|
|
|
fmt.Println(">", cmd.Use, strings.Join(args, " "))
|
2016-07-23 17:37:09 -04:00
|
|
|
}
|
|
|
|
|
2017-10-23 19:35:02 -04:00
|
|
|
// Always print the status code.
|
2017-11-30 17:49:53 -05:00
|
|
|
if rsp.Code == types.CodeTypeOK {
|
|
|
|
fmt.Printf("-> code: OK\n")
|
|
|
|
} else {
|
|
|
|
fmt.Printf("-> code: %d\n", rsp.Code)
|
|
|
|
|
|
|
|
}
|
2017-10-23 19:35:02 -04:00
|
|
|
|
2017-01-23 23:42:09 -08:00
|
|
|
if len(rsp.Data) != 0 {
|
2017-10-23 19:35:02 -04:00
|
|
|
// Do no print this line when using the commit command
|
|
|
|
// because the string comes out as gibberish
|
|
|
|
if cmd.Use != "commit" {
|
|
|
|
fmt.Printf("-> data: %s\n", rsp.Data)
|
|
|
|
}
|
|
|
|
fmt.Printf("-> data.hex: 0x%X\n", rsp.Data)
|
2017-01-23 23:42:09 -08:00
|
|
|
}
|
|
|
|
if rsp.Log != "" {
|
|
|
|
fmt.Printf("-> log: %s\n", rsp.Log)
|
|
|
|
}
|
2017-03-03 18:39:10 -05:00
|
|
|
|
|
|
|
if rsp.Query != nil {
|
|
|
|
fmt.Printf("-> height: %d\n", rsp.Query.Height)
|
|
|
|
if rsp.Query.Key != nil {
|
|
|
|
fmt.Printf("-> key: %s\n", rsp.Query.Key)
|
|
|
|
fmt.Printf("-> key.hex: %X\n", rsp.Query.Key)
|
|
|
|
}
|
|
|
|
if rsp.Query.Value != nil {
|
|
|
|
fmt.Printf("-> value: %s\n", rsp.Query.Value)
|
|
|
|
fmt.Printf("-> value.hex: %X\n", rsp.Query.Value)
|
|
|
|
}
|
|
|
|
if rsp.Query.Proof != nil {
|
2018-09-29 09:03:19 +09:00
|
|
|
fmt.Printf("-> proof: %#v\n", rsp.Query.Proof)
|
2017-03-03 18:39:10 -05:00
|
|
|
}
|
2016-02-08 13:47:47 -08:00
|
|
|
}
|
2016-02-07 19:59:19 -08:00
|
|
|
}
|
2016-07-01 20:22:58 -04:00
|
|
|
|
|
|
|
// NOTE: s is interpreted as a string unless prefixed with 0x
|
2017-01-02 18:49:10 -08:00
|
|
|
func stringOrHexToBytes(s string) ([]byte, error) {
|
|
|
|
if len(s) > 2 && strings.ToLower(s[:2]) == "0x" {
|
2016-07-01 20:22:58 -04:00
|
|
|
b, err := hex.DecodeString(s[2:])
|
|
|
|
if err != nil {
|
2017-01-02 18:49:10 -08:00
|
|
|
err = fmt.Errorf("Error decoding hex argument: %s", err.Error())
|
|
|
|
return nil, err
|
2016-07-01 20:22:58 -04:00
|
|
|
}
|
2017-01-02 18:49:10 -08:00
|
|
|
return b, nil
|
2016-07-01 20:22:58 -04:00
|
|
|
}
|
2017-01-02 18:28:47 -08:00
|
|
|
|
|
|
|
if !strings.HasPrefix(s, "\"") || !strings.HasSuffix(s, "\"") {
|
2017-01-02 18:49:10 -08:00
|
|
|
err := fmt.Errorf("Invalid string arg: \"%s\". Must be quoted or a \"0x\"-prefixed hex string", s)
|
|
|
|
return nil, err
|
2017-01-02 18:28:47 -08:00
|
|
|
}
|
|
|
|
|
2017-01-02 18:49:10 -08:00
|
|
|
return []byte(s[1 : len(s)-1]), nil
|
2016-07-01 20:22:58 -04:00
|
|
|
}
|