Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

R4R: Implement Tx Decode in REST/CLI Clients #4213

Closed
wants to merge 13 commits into from
1 change: 1 addition & 0 deletions .pending/features/gaiacli/3872-Add-gaiacli-tx-
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#3872 Implement a command to decode txs via `gaiacli tx decode`
1 change: 1 addition & 0 deletions .pending/features/gaiarest/3872-Add-POST-txs-de
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#3872 Implement a RESTful endpoint to decode txs via `POST /txs/decode`
2 changes: 1 addition & 1 deletion client/lcd/statik/statik.go

Large diffs are not rendered by default.

30 changes: 30 additions & 0 deletions client/lcd/swagger-ui/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,36 @@ paths:
description: The tx was malformated
500:
description: Server internal error
/txs/decode:
post:
tags:
- Transactions
summary: Decode a transaction from the Amino wire format
description: Decode a transaction (signed or not) from base64-encoded Amino serialized bytes to JSON
consumes:
- application/json
produces:
- application/json
parameters:
- in: body
name: tx
description: The tx to decode
required: true
schema:
type: object
properties:
tx:
type: string
example: SvBiXe4KPqijYZoKFFHEzJ8c2HPAfv2EFUcIhx0yPagwEhTy0vPA+GGhCEslKXa4Af0uB+mfShoMCgVzdGFrZRIDMTAwEgQQwJoM
responses:
200:
description: The tx was successfully decoded
schema:
$ref: "#/definitions/StdTx"
400:
description: The tx was malformated
500:
description: Server internal error
/bank/balances/{address}:
get:
summary: Get the account balances
Expand Down
102 changes: 102 additions & 0 deletions x/auth/client/rest/decode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package rest

import (
"encoding/base64"
"io/ioutil"
"net/http"
yangyanqing marked this conversation as resolved.
Show resolved Hide resolved

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/types/rest"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"

"github.com/spf13/cobra"
amino "github.com/tendermint/go-amino"
)

type (
// DecodeReq defines a tx decoding request.
DecodeReq struct {
Tx string `json:"tx"`
}

// DecodeResp defines a tx decoding response.
DecodeResp authtypes.StdTx
)

// DecodeTxRequestHandlerFn returns the decode tx REST handler. In particular,
// it takes base64-decoded bytes, decodes it from the Amino wire protocol,
// and responds with a json-formatted transaction.
func DecodeTxRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req DecodeReq

body, err := ioutil.ReadAll(r.Body)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}

err = cliCtx.Codec.UnmarshalJSON(body, &req)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}

txBytes, err := base64.StdEncoding.DecodeString(req.Tx)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}

var stdTx authtypes.StdTx
err = cliCtx.Codec.UnmarshalBinaryLengthPrefixed(txBytes, &stdTx)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}

response := DecodeResp(stdTx)
rest.PostProcessResponse(w, cliCtx, response)
}
}

// txDecodeRespStr implements a simple Stringer wrapper for a decoded tx.
type txDecodeRespTx authtypes.StdTx

func (tx txDecodeRespTx) String() string {
return tx.String()
}

// GetDecodeCommand returns the decode command to take Amino-serialized bytes and turn it into
// a JSONified transaction
func GetDecodeCommand(codec *amino.Codec) *cobra.Command {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should live in auth/client/CLI

cmd := &cobra.Command{
Use: "decode [amino-byte-string]",
Short: "Decode an amino-encoded transaction string",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) (err error) {
cliCtx := context.NewCLIContext().WithCodec(codec)

txBytesBase64 := args[0]

txBytes, err := base64.StdEncoding.DecodeString(txBytesBase64)
if err != nil {
return err
}

var stdTx authtypes.StdTx
err = cliCtx.Codec.UnmarshalBinaryLengthPrefixed(txBytes, &stdTx)
if err != nil {
return err
}

response := txDecodeRespTx(stdTx)
_ = cliCtx.PrintOutput(response)

return nil
},
}

return client.PostCommands(cmd)[0]
}
1 change: 1 addition & 0 deletions x/auth/client/rest/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ func RegisterTxRoutes(cliCtx context.CLIContext, r *mux.Router) {
r.HandleFunc("/txs", QueryTxsByEventsRequestHandlerFn(cliCtx)).Methods("GET")
r.HandleFunc("/txs", BroadcastTxRequest(cliCtx)).Methods("POST")
r.HandleFunc("/txs/encode", EncodeTxRequestHandlerFn(cliCtx)).Methods("POST")
r.HandleFunc("/txs/decode", DecodeTxRequestHandlerFn(cliCtx)).Methods("POST")
}
7 changes: 6 additions & 1 deletion x/auth/client/utils/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,12 @@ func PrintUnsignedStdTx(txBldr authtypes.TxBuilder, cliCtx context.CLIContext, m
return err
}

json, err := cliCtx.Codec.MarshalJSON(stdTx)
var json []byte
if viper.GetBool(flags.FlagIndentResponse) {
json, err = cliCtx.Codec.MarshalJSONIndent(stdTx, "", " ")
} else {
json, err = cliCtx.Codec.MarshalJSON(stdTx)
}
if err != nil {
return err
}
Expand Down