From f1dfa62bacff4e5b47f1c45f1febb2137bdb8461 Mon Sep 17 00:00:00 2001 From: Liu-Cheng Xu Date: Mon, 27 Nov 2017 16:57:07 +0800 Subject: [PATCH] Unify json response (#130) * Unify gas-rate json response experimentally * Unify block-height and is-mining * Reuse duplicated code * Don't ignore error check * Unify get-block-by-height and get-block-transactions-count-by-height --- blockchain/reactor.go | 60 ++++++++++++++++++++++++-------- cmd/cobra/commands/block.go | 73 ++++++++++++++++++++++++++++++++++----- cmd/cobra/commands/mining.go | 27 +++++++++++++-- cmd/cobra/commands/transaction.go | 28 +++++++++++++-- 4 files changed, 159 insertions(+), 29 deletions(-) diff --git a/blockchain/reactor.go b/blockchain/reactor.go index b8cbf174..32e35ed8 100755 --- a/blockchain/reactor.go +++ b/blockchain/reactor.go @@ -7,6 +7,7 @@ import ( "fmt" "net/http" "reflect" + "strconv" "time" log "github.com/sirupsen/logrus" @@ -77,6 +78,22 @@ type BlockchainReactor struct { evsw types.EventSwitch } +const ( + SUCCESS = "success" + FAIL = "fail" + ERROR = "error" +) + +// DefaultRawResponse is used as the default response when fail to get data +var DefaultRawResponse = []byte(`{"Status":"error","Msg":"Unable to get data","Data":null}`) + +// Response describes the response standard. +type Response struct { + Status string `json:"status"` + Msg string `json:"msg"` + Data []string `json:"data"` +} + func batchRecover(ctx context.Context, v *interface{}) { if r := recover(); r != nil { var err error @@ -185,7 +202,7 @@ func (bcr *BlockchainReactor) BuildHander() { m.Handle("/peer-count", jsonHandler(bcr.peerCount)) m.Handle("/get-block-by-height", jsonHandler(bcr.getBlockByHeight)) m.Handle("/get-block-transactions-count-by-height", jsonHandler(bcr.getBlockTransactionsCountByHeight)) - m.Handle("/block-height", jsonHandler(bcr.getBlockHeight)) + m.Handle("/block-height", jsonHandler(bcr.blockHeight)) m.Handle("/is-mining", jsonHandler(bcr.isMining)) m.Handle("/gas-rate", jsonHandler(bcr.gasRate)) @@ -451,11 +468,11 @@ func (bcr *BlockchainReactor) getBlockByHash(strHash string) string { return string(ret) } -func (bcr *BlockchainReactor) getBlockByHeight(height uint64) string { +func (bcr *BlockchainReactor) getBlockByHeight(height uint64) []byte { legacyBlock, err := bcr.chain.GetBlockByHeight(height) if err != nil { log.WithField("error", err).Error("Fail to get block by hash") - return err.Error() + return DefaultRawResponse } bcBlock := legacy.MapBlock(legacyBlock) @@ -481,9 +498,10 @@ func (bcr *BlockchainReactor) getBlockByHeight(height uint64) string { ret, err := stdjson.Marshal(res) if err != nil { - return err.Error() + return DefaultRawResponse } - return string(ret) + data := []string{string(ret)} + return resWrapper(data) } func (bcr *BlockchainReactor) getBlockTransactionsCountByHash(strHash string) (int, error) { @@ -528,23 +546,37 @@ func (bcr *BlockchainReactor) isNetSyncing() bool { return bcr.blockKeeper.IsCaughtUp() } -func (bcr *BlockchainReactor) getBlockTransactionsCountByHeight(height uint64) (int, error) { +func (bcr *BlockchainReactor) getBlockTransactionsCountByHeight(height uint64) []byte { legacyBlock, err := bcr.chain.GetBlockByHeight(height) if err != nil { log.WithField("error", err).Error("Fail to get block by hash") - return -1, err + return DefaultRawResponse } - return len(legacyBlock.Transactions), nil + data := []string{strconv.FormatInt(int64(len(legacyBlock.Transactions)), 16)} + log.Infof("%v", data) + return resWrapper(data) +} + +func (bcr *BlockchainReactor) blockHeight() []byte { + data := []string{strconv.FormatUint(bcr.chain.Height(), 16)} + return resWrapper(data) } -func (bcr *BlockchainReactor) getBlockHeight() uint64 { - return bcr.chain.Height() +func (bcr *BlockchainReactor) isMining() []byte { + data := []string{strconv.FormatBool(bcr.mining.IsMining())} + return resWrapper(data) } -func (bcr *BlockchainReactor) isMining() bool { - return bcr.mining.IsMining() +func (bcr *BlockchainReactor) gasRate() []byte { + data := []string{strconv.FormatInt(validation.GasRate, 16)} + return resWrapper(data) } -func (bcr *BlockchainReactor) gasRate() int64 { - return validation.GasRate +func resWrapper(data []string) []byte { + response := Response{Status: SUCCESS, Data: data} + rawResponse, err := stdjson.Marshal(response) + if err != nil { + return DefaultRawResponse + } + return rawResponse } diff --git a/cmd/cobra/commands/block.go b/cmd/cobra/commands/block.go index c9cf7069..190dea1c 100644 --- a/cmd/cobra/commands/block.go +++ b/cmd/cobra/commands/block.go @@ -2,6 +2,7 @@ package commands import ( "context" + "encoding/json" "strconv" "github.com/spf13/cobra" @@ -31,10 +32,28 @@ var blockHeightCmd = &cobra.Command{ Use: "block-height", Short: "Get the number of most recent block", Run: func(cmd *cobra.Command, args []string) { - var response interface{} + var rawResponse []byte + var response blockchain.Response + client := mustRPCClient() - client.Call(context.Background(), "/block-height", nil, &response) - jww.FEEDBACK.Printf("block height: %v\n", response) + client.Call(context.Background(), "/block-height", nil, &rawResponse) + + if err := json.Unmarshal(rawResponse, &response); err != nil { + jww.ERROR.Println(err) + return + } + + if response.Status == blockchain.SUCCESS { + data := response.Data + height, err := strconv.ParseInt(data[0], 16, 64) + if err != nil { + jww.ERROR.Println("Fail to parse response data") + return + } + jww.FEEDBACK.Printf("block height: %v\n", height) + return + } + jww.ERROR.Println(response.Msg) }, } @@ -94,15 +113,32 @@ var getBlockByHeightCmd = &cobra.Command{ jww.ERROR.Println("get-block-by-height args not valid\nUsage: get-block-by-height [height]") return } + ui64, err := strconv.ParseUint(args[0], 10, 64) if err != nil { jww.ERROR.Printf("Invalid height value") return } - var response interface{} + + var rawResponse []byte + var response blockchain.Response + client := mustRPCClient() - client.Call(context.Background(), "/get-block-by-height", ui64, &response) - jww.FEEDBACK.Printf("%v\n", response) + client.Call(context.Background(), "/get-block-by-height", ui64, &rawResponse) + + if err := json.Unmarshal(rawResponse, &response); err != nil { + jww.ERROR.Println(err) + return + } + + if response.Status == blockchain.SUCCESS { + data := response.Data + for idx, d := range data { + jww.FEEDBACK.Printf("%d : %v\n", idx, string(d)) + } + return + } + jww.ERROR.Println(response.Msg) }, } @@ -120,9 +156,28 @@ var getBlockTransactionsCountByHeightCmd = &cobra.Command{ jww.ERROR.Printf("Invalid height value") return } - var response interface{} + + var rawResponse []byte + var response blockchain.Response + client := mustRPCClient() - client.Call(context.Background(), "/get-block-transactions-count-by-height", ui64, &response) - jww.FEEDBACK.Printf("transactions count: %v\n", response) + client.Call(context.Background(), "/get-block-transactions-count-by-height", ui64, &rawResponse) + + if err := json.Unmarshal(rawResponse, &response); err != nil { + jww.ERROR.Println(err) + return + } + + if response.Status == blockchain.SUCCESS { + data := response.Data + cnt, err := strconv.ParseInt(data[0], 16, 64) + if err != nil { + jww.ERROR.Println("Fail to parse response data") + return + } + jww.FEEDBACK.Printf("transactions count: %v\n", cnt) + return + } + jww.ERROR.Println(response.Msg) }, } diff --git a/cmd/cobra/commands/mining.go b/cmd/cobra/commands/mining.go index 289d4aa2..b5bb8ea1 100644 --- a/cmd/cobra/commands/mining.go +++ b/cmd/cobra/commands/mining.go @@ -2,18 +2,39 @@ package commands import ( "context" + "encoding/json" + "strconv" "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" + + "github.com/bytom/blockchain" ) var isMiningCmd = &cobra.Command{ Use: "is-mining", Short: "If client is actively mining new blocks", Run: func(cmd *cobra.Command, args []string) { - var response interface{} + var rawResponse []byte + var response blockchain.Response client := mustRPCClient() - client.Call(context.Background(), "/is-mining", nil, &response) - jww.FEEDBACK.Printf("is mining: %v\n", response) + client.Call(context.Background(), "/is-mining", nil, &rawResponse) + + if err := json.Unmarshal(rawResponse, &response); err != nil { + jww.ERROR.Println(err) + return + } + + if response.Status == blockchain.SUCCESS { + data := response.Data + res, err := strconv.ParseBool(data[0]) + if err != nil { + jww.ERROR.Println("Fail to parse response data") + return + } + jww.FEEDBACK.Printf("is mining: %v\n", res) + return + } + jww.ERROR.Println(response.Msg) }, } diff --git a/cmd/cobra/commands/transaction.go b/cmd/cobra/commands/transaction.go index e8223e81..ade332f6 100644 --- a/cmd/cobra/commands/transaction.go +++ b/cmd/cobra/commands/transaction.go @@ -2,18 +2,40 @@ package commands import ( "context" + "encoding/json" + "strconv" "github.com/spf13/cobra" jww "github.com/spf13/jwalterweatherman" + + "github.com/bytom/blockchain" ) var gasRateCmd = &cobra.Command{ Use: "gas-rate", Short: "Print the current gas rate", Run: func(cmd *cobra.Command, args []string) { - var response interface{} + var rawResponse []byte + var response blockchain.Response + client := mustRPCClient() - client.Call(context.Background(), "/gas-rate", nil, &response) - jww.FEEDBACK.Printf("gas rate: %v\n", response) + client.Call(context.Background(), "/gas-rate", nil, &rawResponse) + + if err := json.Unmarshal(rawResponse, &response); err != nil { + jww.ERROR.Println(err) + return + } + + if response.Status == blockchain.SUCCESS { + data := response.Data + i, err := strconv.ParseInt(data[0], 16, 64) + if err != nil { + jww.ERROR.Println("Fail to parse response data") + return + } + jww.FEEDBACK.Printf("gas rate: %v\n", i) + return + } + jww.ERROR.Println(response.Msg) }, } -- 2.11.0