Skip to content

Commit

Permalink
Merge PR #3642: Tx Query return values
Browse files Browse the repository at this point in the history
  • Loading branch information
jackzampolin authored and cwgoes committed Feb 15, 2019
1 parent c0eec30 commit 5ccad47
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 30 deletions.
1 change: 1 addition & 0 deletions PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
BREAKING CHANGES

* Gaia REST API
* [\#3642](https://github.com/cosmos/cosmos-sdk/pull/3642) `GET /tx/{hash}` now returns `404` instead of `500` if the transaction is not found

* Gaia CLI

Expand Down
12 changes: 12 additions & 0 deletions client/lcd/lcd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"net/http"
"os"
"regexp"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -503,6 +504,17 @@ func TestTxs(t *testing.T) {
txs = getTransactions(t, port, fmt.Sprintf("recipient=%s", receiveAddr.String()))
require.Len(t, txs, 1)
require.Equal(t, resultTx.Height, txs[0].Height)

// query transaction that doesn't exist
validTxHash := "9ADBECAAD8DACBEC3F4F535704E7CF715C765BDCEDBEF086AFEAD31BA664FB0B"
res, body := getTransactionRequest(t, port, validTxHash)
require.True(t, strings.Contains(body, validTxHash))
require.Equal(t, http.StatusNotFound, res.StatusCode)

// bad query string
res, body = getTransactionRequest(t, port, "badtxhash")
require.True(t, strings.Contains(body, "encoding/hex"))
require.Equal(t, http.StatusInternalServerError, res.StatusCode)
}

func TestPoolParamsQuery(t *testing.T) {
Expand Down
6 changes: 5 additions & 1 deletion client/lcd/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -513,14 +513,18 @@ func getValidatorSets(t *testing.T, port string, height int, expectFail bool) rp
// GET /txs/{hash} get tx by hash
func getTransaction(t *testing.T, port string, hash string) sdk.TxResponse {
var tx sdk.TxResponse
res, body := Request(t, port, "GET", fmt.Sprintf("/txs/%s", hash), nil)
res, body := getTransactionRequest(t, port, hash)
require.Equal(t, http.StatusOK, res.StatusCode, body)

err := cdc.UnmarshalJSON([]byte(body), &tx)
require.NoError(t, err)
return tx
}

func getTransactionRequest(t *testing.T, port, hash string) (*http.Response, string) {
return Request(t, port, "GET", fmt.Sprintf("/txs/%s", hash), nil)
}

// POST /txs broadcast txs

// GET /txs search transactions
Expand Down
64 changes: 35 additions & 29 deletions client/tx/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/hex"
"fmt"
"net/http"
"strings"

"github.com/gorilla/mux"
"github.com/spf13/cobra"
Expand All @@ -26,18 +27,18 @@ func QueryTxCmd(cdc *codec.Codec) *cobra.Command {
Short: "Matches this txhash over all committed blocks",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
// find the key to look up the account
hashHexStr := args[0]

cliCtx := context.NewCLIContext().WithCodec(cdc)

output, err := queryTx(cdc, cliCtx, hashHexStr)
output, err := queryTx(cdc, cliCtx, args[0])
if err != nil {
return err
}

fmt.Println(string(output))
return nil
if output.Empty() {
return fmt.Errorf("No transaction found with hash %s", args[0])
}

return cliCtx.PrintOutput(output)
},
}

Expand All @@ -48,50 +49,46 @@ func QueryTxCmd(cdc *codec.Codec) *cobra.Command {
return cmd
}

func queryTx(cdc *codec.Codec, cliCtx context.CLIContext, hashHexStr string) ([]byte, error) {
func queryTx(cdc *codec.Codec, cliCtx context.CLIContext, hashHexStr string) (out sdk.TxResponse, err error) {
hash, err := hex.DecodeString(hashHexStr)
if err != nil {
return nil, err
return out, err
}

node, err := cliCtx.GetNode()
if err != nil {
return nil, err
return out, err
}

res, err := node.Tx(hash, !cliCtx.TrustNode)
if err != nil {
return nil, err
return out, err
}

if !cliCtx.TrustNode {
err := ValidateTxResult(cliCtx, res)
if err != nil {
return nil, err
if err = ValidateTxResult(cliCtx, res); err != nil {
return out, err
}
}

info, err := formatTxResult(cdc, res)
if err != nil {
return nil, err
if out, err = formatTxResult(cdc, res); err != nil {
return out, err
}

if cliCtx.Indent {
return cdc.MarshalJSONIndent(info, "", " ")
}
return cdc.MarshalJSON(info)
return out, nil
}

// ValidateTxResult performs transaction verification
func ValidateTxResult(cliCtx context.CLIContext, res *ctypes.ResultTx) error {
check, err := cliCtx.Verify(res.Height)
if err != nil {
return err
}

err = res.Proof.Validate(check.Header.DataHash)
if err != nil {
return err
if !cliCtx.TrustNode {
check, err := cliCtx.Verify(res.Height)
if err != nil {
return err
}
err = res.Proof.Validate(check.Header.DataHash)
if err != nil {
return err
}
}
return nil
}
Expand All @@ -118,17 +115,26 @@ func parseTx(cdc *codec.Codec, txBytes []byte) (sdk.Tx, error) {

// REST

// transaction query REST handler
// QueryTxRequestHandlerFn transaction query REST handler
func QueryTxRequestHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
hashHexStr := vars["hash"]

output, err := queryTx(cdc, cliCtx, hashHexStr)
if err != nil {
if strings.Contains(err.Error(), hashHexStr) {
rest.WriteErrorResponse(w, http.StatusNotFound, err.Error())
return
}
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}

if output.Empty() {
rest.WriteErrorResponse(w, http.StatusNotFound, fmt.Sprintf("no transaction found with hash %s", hashHexStr))
}

rest.PostProcessResponse(w, cdc, output, cliCtx.Indent)
}
}
9 changes: 9 additions & 0 deletions types/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type TxResponse struct {
Tx Tx `json:"tx,omitempty"`
}

// NewResponseResultTx returns a TxResponse given a ResultTx from tendermint
func NewResponseResultTx(res *ctypes.ResultTx, tx Tx) TxResponse {
if res == nil {
return TxResponse{}
Expand All @@ -73,6 +74,7 @@ func NewResponseResultTx(res *ctypes.ResultTx, tx Tx) TxResponse {
}
}

// NewResponseFormatBroadcastTxCommit returns a TxResponse given a ResultBroadcastTxCommit from tendermint
func NewResponseFormatBroadcastTxCommit(res *ctypes.ResultBroadcastTxCommit) TxResponse {
if res == nil {
return TxResponse{}
Expand All @@ -95,8 +97,10 @@ func NewResponseFormatBroadcastTxCommit(res *ctypes.ResultBroadcastTxCommit) TxR
Tags: TagsToStringTags(res.DeliverTx.Tags),
Codespace: res.DeliverTx.Codespace,
}

}

// NewResponseFormatBroadcastTx returns a TxResponse given a ResultBroadcastTx from tendermint
func NewResponseFormatBroadcastTx(res *ctypes.ResultBroadcastTx) TxResponse {
if res == nil {
return TxResponse{}
Expand Down Expand Up @@ -156,3 +160,8 @@ func (r TxResponse) String() string {

return strings.TrimSpace(sb.String())
}

// Empty returns true if the response is empty
func (r TxResponse) Empty() bool {
return r.TxHash == "" && r.Log == ""
}

0 comments on commit 5ccad47

Please sign in to comment.