diff --git a/PENDING.md b/PENDING.md index 0212f66571..6c1073f2fb 100644 --- a/PENDING.md +++ b/PENDING.md @@ -10,6 +10,10 @@ * `password` and `generate_only` have been removed from the `base_req` object * All txs that used to sign or use the Keybase now only generate the tx * `keys` routes completely removed +* [\#3692] Update tx encoding and broadcasting endpoints: + * Remove duplicate broadcasting endpoints in favor of POST @ `/txs` + * The `Tx` field now accepts a `StdTx` and not raw tx bytes + * Move encoding endpoint to `/txs/encode` ### Gaia CLI diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 03c9a36717..ccb5895dad 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -15,6 +15,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/keys" + clienttx "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/cmd/gaia/app" "github.com/cosmos/cosmos-sdk/crypto/keys/mintkey" "github.com/cosmos/cosmos-sdk/tests" @@ -292,12 +293,9 @@ func TestEncodeTx(t *testing.T) { var tx auth.StdTx cdc.UnmarshalJSON([]byte(body), &tx) - // build the request - encodeReq := struct { - Tx auth.StdTx `json:"tx"` - }{Tx: tx} - encodedJSON, _ := cdc.MarshalJSON(encodeReq) - res, body = Request(t, port, "POST", "/tx/encode", encodedJSON) + req := clienttx.EncodeReq{Tx: tx} + encodedJSON, _ := cdc.MarshalJSON(req) + res, body = Request(t, port, "POST", "/txs/encode", encodedJSON) // Make sure it came back ok, and that we can decode it back to the transaction // 200 response. diff --git a/client/lcd/swagger-ui/swagger.yaml b/client/lcd/swagger-ui/swagger.yaml index c4380c380a..803da4aedf 100644 --- a/client/lcd/swagger-ui/swagger.yaml +++ b/client/lcd/swagger-ui/swagger.yaml @@ -241,8 +241,8 @@ paths: post: tags: - ICS0 - summary: broadcast Tx - description: broadcast tx with tendermint rpc + summary: Broadcast a signed tx + description: Broadcast a signed tx to a full node consumes: - application/json produces: @@ -250,57 +250,28 @@ paths: parameters: - in: body name: txBroadcast - description: Build a StdTx transaction and serilize it to a byte array with amino, then the `"tx"` field in the post body will be the base64 encoding of the byte array. The supported return types includes `"block"`(return after tx commit), `"sync"`(return afer CheckTx) and `"async"`(return right away). - required: true - schema: - type: object - properties: - tx: - type: string - return: - type: string - example: block - responses: - 200: - description: Broadcast tx result - schema: - $ref: "#/definitions/BroadcastTxCommitResult" - 500: - description: Internal Server Error - /tx/broadcast: - post: - tags: - - ICS20 - summary: Send a signed Tx - description: Send a signed Tx to a Gaiad full node - consumes: - - application/json - produces: - - application/json - parameters: - - in: body - name: txBroadcast - description: broadcast tx + description: The tx must be a signed StdTx. The supported return types includes `"block"`(return after tx commit), `"sync"`(return afer CheckTx) and `"async"`(return right away). required: true schema: type: object properties: tx: $ref: "#/definitions/StdTx" + return: + type: string + example: block responses: - 202: - description: Tx was send and will probably be added to the next block + 200: + description: Tx broadcasting result schema: $ref: "#/definitions/BroadcastTxCommitResult" - 400: - description: The Tx was malformated 500: - description: Server internal error - /tx/encode: + description: Internal Server Error + /txs/encode: post: tags: - - ICS20 - summary: Encode a transaction to wire format + - ICS0 + summary: Encode a transaction to the Amino wire format description: Encode a transaction (signed or not) from JSON to base64-encoded Amino serialized bytes consumes: - application/json @@ -309,7 +280,7 @@ paths: parameters: - in: body name: tx - description: The transaction to encode + description: The tx to encode required: true schema: type: object @@ -318,15 +289,15 @@ paths: $ref: "#/definitions/StdTx" responses: 200: - description: Transaction was successfully decoded and re-encoded + description: The tx was successfully decoded and re-encoded schema: type: object properties: tx: type: string - example: The base64-encoded Amino-serialized bytes for the transaction + example: The base64-encoded Amino-serialized bytes for the tx 400: - description: The Tx was malformated + description: The tx was malformated 500: description: Server internal error /bank/balances/{address}: diff --git a/client/lcd/test_helpers.go b/client/lcd/test_helpers.go index 361de57049..6d5694cdf2 100644 --- a/client/lcd/test_helpers.go +++ b/client/lcd/test_helpers.go @@ -24,6 +24,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/rpc" "github.com/cosmos/cosmos-sdk/client/tx" + clienttx "github.com/cosmos/cosmos-sdk/client/tx" gapp "github.com/cosmos/cosmos-sdk/cmd/gaia/app" "github.com/cosmos/cosmos-sdk/codec" crkeys "github.com/cosmos/cosmos-sdk/crypto/keys" @@ -649,12 +650,12 @@ func getAccount(t *testing.T, port string, addr sdk.AccAddress) auth.Account { // POST /tx/broadcast Send a signed Tx func doBroadcast(t *testing.T, port string, tx auth.StdTx) (*http.Response, string) { - txReq := authrest.BroadcastReq{Tx: tx, Return: "block"} + txReq := clienttx.BroadcastReq{Tx: tx, Return: "block"} req, err := cdc.MarshalJSON(txReq) require.Nil(t, err) - return Request(t, port, "POST", "/tx/broadcast", req) + return Request(t, port, "POST", "/txs", req) } // doTransfer performs a balance transfer with auto gas calculation. It also signs diff --git a/client/tx/broadcast.go b/client/tx/broadcast.go index e75a8cdc44..a0437b1cd1 100644 --- a/client/tx/broadcast.go +++ b/client/tx/broadcast.go @@ -2,12 +2,19 @@ package tx import ( "net/http" + "strings" + "github.com/spf13/cobra" + amino "github.com/tendermint/go-amino" + + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/types/rest" + "github.com/cosmos/cosmos-sdk/x/auth" "io/ioutil" "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/utils" "github.com/cosmos/cosmos-sdk/codec" ) @@ -20,44 +27,93 @@ const ( flagBlock = "block" ) -// BroadcastBody Tx Broadcast Body -type BroadcastBody struct { - TxBytes []byte `json:"tx"` - Return string `json:"return"` +// BroadcastReq defines a tx broadcasting request. +type BroadcastReq struct { + Tx auth.StdTx `json:"tx"` + Return string `json:"return"` } -// BroadcastTxRequest REST Handler -// nolint: gocyclo +// BroadcastTxRequest implements a tx broadcasting handler that is responsible +// for broadcasting a valid and signed tx to a full node. The tx can be +// broadcasted via a sync|async|block mechanism. func BroadcastTxRequest(cliCtx context.CLIContext, cdc *codec.Codec) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - var m BroadcastBody + var req BroadcastReq + body, err := ioutil.ReadAll(r.Body) if err != nil { rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return } - err = cdc.UnmarshalJSON(body, &m) + + err = cdc.UnmarshalJSON(body, &req) if err != nil { rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) return } + + txBytes, err := cdc.MarshalBinaryLengthPrefixed(req.Tx) + if err != nil { + rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + var res interface{} - switch m.Return { + switch req.Return { case flagBlock: - res, err = cliCtx.BroadcastTx(m.TxBytes) + res, err = cliCtx.BroadcastTx(txBytes) + case flagSync: - res, err = cliCtx.BroadcastTxSync(m.TxBytes) + res, err = cliCtx.BroadcastTxSync(txBytes) + case flagAsync: - res, err = cliCtx.BroadcastTxAsync(m.TxBytes) + res, err = cliCtx.BroadcastTxAsync(txBytes) + default: rest.WriteErrorResponse(w, http.StatusInternalServerError, "unsupported return type. supported types: block, sync, async") return } + if err != nil { rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) return } + rest.PostProcessResponse(w, cdc, res, cliCtx.Indent) } } + +// GetBroadcastCommand returns the tx broadcast command. +func GetBroadcastCommand(codec *amino.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "broadcast [file_path]", + Short: "Broadcast transactions generated offline", + Long: strings.TrimSpace(`Broadcast transactions created with the --generate-only +flag and signed with the sign command. Read a transaction from [file_path] and +broadcast it to a node. If you supply a dash (-) argument in place of an input +filename, the command reads from standard input. + +$ gaiacli tx broadcast ./mytxn.json +`), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) (err error) { + cliCtx := context.NewCLIContext().WithCodec(codec) + stdTx, err := utils.ReadStdTxFromFile(cliCtx.Codec, args[0]) + if err != nil { + return + } + + txBytes, err := cliCtx.Codec.MarshalBinaryLengthPrefixed(stdTx) + if err != nil { + return + } + + res, err := cliCtx.BroadcastTx(txBytes) + cliCtx.PrintOutput(res) + return err + }, + } + + return client.PostCommands(cmd)[0] +} diff --git a/client/tx/encode.go b/client/tx/encode.go new file mode 100644 index 0000000000..75670aade9 --- /dev/null +++ b/client/tx/encode.go @@ -0,0 +1,107 @@ +package tx + +import ( + "encoding/base64" + "io/ioutil" + "net/http" + + "github.com/spf13/cobra" + amino "github.com/tendermint/go-amino" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/context" + "github.com/cosmos/cosmos-sdk/client/utils" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/types/rest" + "github.com/cosmos/cosmos-sdk/x/auth" +) + +type ( + // EncodeReq defines a tx encoding request. + EncodeReq struct { + Tx auth.StdTx `json:"tx"` + } + + // EncodeResp defines a tx encoding response. + EncodeResp struct { + Tx string `json:"tx"` + } +) + +// EncodeTxRequestHandlerFn returns the encode tx REST handler. In particular, +// it takes a json-formatted transaction, encodes it to the Amino wire protocol, +// and responds with base64-encoded bytes. +func EncodeTxRequestHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req EncodeReq + + body, err := ioutil.ReadAll(r.Body) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + err = cdc.UnmarshalJSON(body, &req) + if err != nil { + rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) + return + } + + // re-encode it via the Amino wire protocol + txBytes, err := cliCtx.Codec.MarshalBinaryLengthPrefixed(req.Tx) + if err != nil { + rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) + return + } + + // base64 encode the encoded tx bytes + txBytesBase64 := base64.StdEncoding.EncodeToString(txBytes) + + response := EncodeResp{Tx: txBytesBase64} + rest.PostProcessResponse(w, cdc, response, cliCtx.Indent) + } +} + +// txEncodeRespStr implements a simple Stringer wrapper for a encoded tx. +type txEncodeRespStr string + +func (txr txEncodeRespStr) String() string { + return string(txr) +} + +// GetEncodeCommand returns the encode command to take a JSONified transaction and turn it into +// Amino-serialized bytes +func GetEncodeCommand(codec *amino.Codec) *cobra.Command { + cmd := &cobra.Command{ + Use: "encode [file]", + Short: "Encode transactions generated offline", + Long: `Encode transactions created with the --generate-only flag and signed with the sign command. +Read a transaction from , serialize it to the Amino wire protocol, and output it as base64. +If you supply a dash (-) argument in place of an input filename, the command reads from standard input.`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) (err error) { + cliCtx := context.NewCLIContext().WithCodec(codec) + + stdTx, err := utils.ReadStdTxFromFile(cliCtx.Codec, args[0]) + if err != nil { + return + } + + // re-encode it via the Amino wire protocol + txBytes, err := cliCtx.Codec.MarshalBinaryLengthPrefixed(stdTx) + if err != nil { + return err + } + + // base64 encode the encoded tx bytes + txBytesBase64 := base64.StdEncoding.EncodeToString(txBytes) + + response := txEncodeRespStr(txBytesBase64) + cliCtx.PrintOutput(response) + + return nil + }, + } + + return client.PostCommands(cmd)[0] +} diff --git a/client/tx/root.go b/client/tx/root.go index 5cd7eca0b8..104e0a57cb 100644 --- a/client/tx/root.go +++ b/client/tx/root.go @@ -12,4 +12,5 @@ func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec) r.HandleFunc("/txs/{hash}", QueryTxRequestHandlerFn(cdc, cliCtx)).Methods("GET") r.HandleFunc("/txs", SearchTxRequestHandlerFn(cliCtx, cdc)).Methods("GET") r.HandleFunc("/txs", BroadcastTxRequest(cliCtx, cdc)).Methods("POST") + r.HandleFunc("/txs/encode", EncodeTxRequestHandlerFn(cdc, cliCtx)).Methods("POST") } diff --git a/client/utils/utils.go b/client/utils/utils.go index 633a7e28a3..8d1c0b4943 100644 --- a/client/utils/utils.go +++ b/client/utils/utils.go @@ -3,6 +3,7 @@ package utils import ( "bytes" "fmt" + "io/ioutil" "os" "github.com/cosmos/cosmos-sdk/client" @@ -124,20 +125,27 @@ func CalculateGas(queryFunc func(string, common.HexBytes) ([]byte, error), cdc * // PrintUnsignedStdTx builds an unsigned StdTx and prints it to os.Stdout. // Don't perform online validation or lookups if offline is true. -func PrintUnsignedStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg, offline bool) (err error) { +func PrintUnsignedStdTx( + txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg, offline bool, +) (err error) { + var stdTx auth.StdTx + if offline { stdTx, err = buildUnsignedStdTxOffline(txBldr, cliCtx, msgs) } else { stdTx, err = buildUnsignedStdTx(txBldr, cliCtx, msgs) } + if err != nil { return } + json, err := cliCtx.Codec.MarshalJSON(stdTx) if err == nil { fmt.Fprintf(cliCtx.Output, "%s\n", json) } + return } @@ -204,6 +212,23 @@ func SignStdTxWithSignerAddress(txBldr authtxb.TxBuilder, cliCtx context.CLICont return txBldr.SignStdTx(name, passphrase, stdTx, false) } +// Read and decode a StdTx from the given filename. Can pass "-" to read from stdin. +func ReadStdTxFromFile(cdc *amino.Codec, filename string) (stdTx auth.StdTx, err error) { + var bytes []byte + if filename == "-" { + bytes, err = ioutil.ReadAll(os.Stdin) + } else { + bytes, err = ioutil.ReadFile(filename) + } + if err != nil { + return + } + if err = cdc.UnmarshalJSON(bytes, &stdTx); err != nil { + return + } + return +} + func populateAccountFromState(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, addr sdk.AccAddress) (authtxb.TxBuilder, error) { if txBldr.AccountNumber() == 0 { diff --git a/client/utils/utils_test.go b/client/utils/utils_test.go index d5ed6205eb..a0d0b93868 100644 --- a/client/utils/utils_test.go +++ b/client/utils/utils_test.go @@ -3,19 +3,19 @@ package utils import ( "encoding/json" "errors" + "io/ioutil" + "os" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto/ed25519" - - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/x/auth" - - "github.com/stretchr/testify/assert" "github.com/tendermint/tendermint/libs/common" "github.com/cosmos/cosmos-sdk/cmd/gaia/app" + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" ) var ( @@ -110,3 +110,32 @@ func makeCodec() *codec.Codec { cdc.RegisterConcrete(sdk.TestMsg{}, "cosmos-sdk/Test", nil) return cdc } + +func TestReadStdTxFromFile(t *testing.T) { + cdc := codec.New() + sdk.RegisterCodec(cdc) + + // Build a test transaction + fee := auth.NewStdFee(50000, sdk.Coins{sdk.NewInt64Coin("atom", 150)}) + stdTx := auth.NewStdTx([]sdk.Msg{}, fee, []auth.StdSignature{}, "foomemo") + + // Write it to the file + encodedTx, _ := cdc.MarshalJSON(stdTx) + jsonTxFile := writeToNewTempFile(t, string(encodedTx)) + defer os.Remove(jsonTxFile.Name()) + + // Read it back + decodedTx, err := ReadStdTxFromFile(cdc, jsonTxFile.Name()) + require.Nil(t, err) + require.Equal(t, decodedTx.Memo, "foomemo") +} + +func writeToNewTempFile(t *testing.T, data string) *os.File { + fp, err := ioutil.TempFile(os.TempDir(), "client_tx_test") + require.Nil(t, err) + + _, err = fp.WriteString(data) + require.Nil(t, err) + + return fp +} diff --git a/cmd/gaia/cmd/gaiacli/main.go b/cmd/gaia/cmd/gaiacli/main.go index f49a0e3ac7..8bdd645e90 100644 --- a/cmd/gaia/cmd/gaiacli/main.go +++ b/cmd/gaia/cmd/gaiacli/main.go @@ -141,8 +141,8 @@ func txCmd(cdc *amino.Codec, mc []sdk.ModuleClients) *cobra.Command { client.LineBreak, authcmd.GetSignCommand(cdc), authcmd.GetMultiSignCommand(cdc), - authcmd.GetBroadcastCommand(cdc), - authcmd.GetEncodeCommand(cdc), + tx.GetBroadcastCommand(cdc), + tx.GetEncodeCommand(cdc), client.LineBreak, ) diff --git a/x/auth/client/cli/broadcast.go b/x/auth/client/cli/broadcast.go deleted file mode 100644 index 8dc1992b59..0000000000 --- a/x/auth/client/cli/broadcast.go +++ /dev/null @@ -1,45 +0,0 @@ -package cli - -import ( - "strings" - - "github.com/spf13/cobra" - amino "github.com/tendermint/go-amino" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/context" - authclient "github.com/cosmos/cosmos-sdk/x/auth/client" -) - -// GetSignCommand returns the sign command -func GetBroadcastCommand(codec *amino.Codec) *cobra.Command { - cmd := &cobra.Command{ - Use: "broadcast [file_path]", - Short: "Broadcast transactions generated offline", - Long: strings.TrimSpace(`Broadcast transactions created with the --generate-only flag and signed with the sign command. -Read a transaction from [file_path] and broadcast it to a node. If you supply a dash (-) argument -in place of an input filename, the command reads from standard input. - -$ gaiacli tx broadcast ./mytxn.json -`), - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) (err error) { - cliCtx := context.NewCLIContext().WithCodec(codec) - stdTx, err := authclient.ReadStdTxFromFile(cliCtx.Codec, args[0]) - if err != nil { - return - } - - txBytes, err := cliCtx.Codec.MarshalBinaryLengthPrefixed(stdTx) - if err != nil { - return - } - - res, err := cliCtx.BroadcastTx(txBytes) - cliCtx.PrintOutput(res) - return err - }, - } - - return client.PostCommands(cmd)[0] -} diff --git a/x/auth/client/cli/encode.go b/x/auth/client/cli/encode.go deleted file mode 100644 index 0717915515..0000000000 --- a/x/auth/client/cli/encode.go +++ /dev/null @@ -1,55 +0,0 @@ -package cli - -import ( - "encoding/base64" - - "github.com/spf13/cobra" - amino "github.com/tendermint/go-amino" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/context" - authclient "github.com/cosmos/cosmos-sdk/x/auth/client" -) - -// PrintOutput requires a Stringer, so we wrap string -type encodeResp string - -func (e encodeResp) String() string { - return string(e) -} - -// GetEncodeCommand returns the encode command to take a JSONified transaction and turn it into -// Amino-serialized bytes -func GetEncodeCommand(codec *amino.Codec) *cobra.Command { - cmd := &cobra.Command{ - Use: "encode [file]", - Short: "encode transactions generated offline", - Long: `Encode transactions created with the --generate-only flag and signed with the sign command. -Read a transaction from , serialize it to the Amino wire protocol, and output it as base64. -If you supply a dash (-) argument in place of an input filename, the command reads from standard input.`, - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) (err error) { - cliCtx := context.NewCLIContext().WithCodec(codec) - - stdTx, err := authclient.ReadStdTxFromFile(cliCtx.Codec, args[0]) - if err != nil { - return - } - - txBytes, err := cliCtx.Codec.MarshalBinaryLengthPrefixed(stdTx) - if err != nil { - return err - } - - // Encode the bytes to base64 - txBytesBase64 := base64.StdEncoding.EncodeToString(txBytes) - - // Write it back - response := encodeResp(txBytesBase64) - cliCtx.PrintOutput(response) - return nil - }, - } - - return client.PostCommands(cmd)[0] -} diff --git a/x/auth/client/cli/multisign.go b/x/auth/client/cli/multisign.go index fdcd1d1424..f1961a7a36 100644 --- a/x/auth/client/cli/multisign.go +++ b/x/auth/client/cli/multisign.go @@ -14,9 +14,9 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/keys" + "github.com/cosmos/cosmos-sdk/client/utils" crkeys "github.com/cosmos/cosmos-sdk/crypto/keys" "github.com/cosmos/cosmos-sdk/x/auth" - authclient "github.com/cosmos/cosmos-sdk/x/auth/client" authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" ) @@ -52,7 +52,7 @@ recommended to set such parameters manually. func makeMultiSignCmd(cdc *amino.Codec) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) (err error) { - stdTx, err := authclient.ReadStdTxFromFile(cdc, args[0]) + stdTx, err := utils.ReadStdTxFromFile(cdc, args[0]) if err != nil { return } diff --git a/x/auth/client/cli/sign.go b/x/auth/client/cli/sign.go index 7264f2d3f8..3d6b9da5e5 100644 --- a/x/auth/client/cli/sign.go +++ b/x/auth/client/cli/sign.go @@ -13,7 +13,6 @@ import ( "github.com/cosmos/cosmos-sdk/client/utils" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/auth" - authclient "github.com/cosmos/cosmos-sdk/x/auth/client" authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder" ) @@ -74,7 +73,7 @@ be generated via the 'multisign' command. func makeSignCmd(cdc *amino.Codec) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) (err error) { - stdTx, err := authclient.ReadStdTxFromFile(cdc, args[0]) + stdTx, err := utils.ReadStdTxFromFile(cdc, args[0]) if err != nil { return } diff --git a/x/auth/client/rest/broadcast.go b/x/auth/client/rest/broadcast.go deleted file mode 100644 index 2e0cc9c42a..0000000000 --- a/x/auth/client/rest/broadcast.go +++ /dev/null @@ -1,53 +0,0 @@ -package rest - -import ( - "io/ioutil" - "net/http" - - "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/types/rest" - "github.com/cosmos/cosmos-sdk/x/auth" -) - -type broadcastBody struct { - Tx auth.StdTx `json:"tx"` -} - -// BroadcastTxRequestHandlerFn returns the broadcast tx REST handler -func BroadcastTxRequestHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - var m broadcastBody - if ok := unmarshalBodyOrReturnBadRequest(cliCtx, w, r, &m); !ok { - return - } - - txBytes, err := cliCtx.Codec.MarshalBinaryLengthPrefixed(m.Tx) - if err != nil { - rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) - return - } - - res, err := cliCtx.BroadcastTx(txBytes) - if err != nil { - rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) - return - } - - rest.PostProcessResponse(w, cdc, res, cliCtx.Indent) - } -} - -func unmarshalBodyOrReturnBadRequest(cliCtx context.CLIContext, w http.ResponseWriter, r *http.Request, m interface{}) bool { - body, err := ioutil.ReadAll(r.Body) - if err != nil { - rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) - return false - } - err = cliCtx.Codec.UnmarshalJSON(body, m) - if err != nil { - rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error()) - return false - } - return true -} diff --git a/x/auth/client/rest/encode.go b/x/auth/client/rest/encode.go deleted file mode 100644 index 97c25f15f6..0000000000 --- a/x/auth/client/rest/encode.go +++ /dev/null @@ -1,47 +0,0 @@ -package rest - -import ( - "encoding/base64" - "net/http" - - "github.com/cosmos/cosmos-sdk/client/context" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/types/rest" - - "github.com/cosmos/cosmos-sdk/x/auth" -) - -type encodeReq struct { - Tx auth.StdTx `json:"tx"` -} - -type encodeResp struct { - Tx string `json:"tx"` -} - -// EncodeTxRequestHandlerFn returns the encode tx REST handler. In particular, it takes a -// json-formatted transaction, encodes it to the Amino wire protocol, and responds with -// base64-encoded bytes -func EncodeTxRequestHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - var m encodeReq - // Decode the transaction from JSON - if ok := unmarshalBodyOrReturnBadRequest(cliCtx, w, r, &m); !ok { - return - } - - // Re-encode it to the wire protocol - txBytes, err := cliCtx.Codec.MarshalBinaryLengthPrefixed(m.Tx) - if err != nil { - rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error()) - return - } - - // Encode the bytes to base64 - txBytesBase64 := base64.StdEncoding.EncodeToString(txBytes) - - // Write it back - response := encodeResp{Tx: txBytesBase64} - rest.PostProcessResponse(w, cdc, response, cliCtx.Indent) - } -} diff --git a/x/auth/client/rest/query.go b/x/auth/client/rest/query.go index 9e57bf9fd1..e7345f3d45 100644 --- a/x/auth/client/rest/query.go +++ b/x/auth/client/rest/query.go @@ -19,18 +19,11 @@ func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *codec.Codec, "/auth/accounts/{address}", QueryAccountRequestHandlerFn(storeName, cdc, context.GetAccountDecoder(cdc), cliCtx), ).Methods("GET") + r.HandleFunc( "/bank/balances/{address}", QueryBalancesRequestHandlerFn(storeName, cdc, context.GetAccountDecoder(cdc), cliCtx), ).Methods("GET") - r.HandleFunc( - "/tx/broadcast", - BroadcastTxRequestHandlerFn(cdc, cliCtx), - ).Methods("POST") - r.HandleFunc( - "/tx/encode", - EncodeTxRequestHandlerFn(cdc, cliCtx), - ).Methods("POST") } // query accountREST Handler diff --git a/x/auth/client/rest/requests.go b/x/auth/client/rest/requests.go deleted file mode 100644 index 5fa6a8ec6a..0000000000 --- a/x/auth/client/rest/requests.go +++ /dev/null @@ -1,9 +0,0 @@ -package rest - -import "github.com/cosmos/cosmos-sdk/x/auth" - -// BroadcastReq requests broadcasting a transaction -type BroadcastReq struct { - Tx auth.StdTx `json:"tx"` - Return string `json:"return"` // TODO: Do we need this? -} diff --git a/x/auth/client/util.go b/x/auth/client/util.go deleted file mode 100644 index 94eb480d6a..0000000000 --- a/x/auth/client/util.go +++ /dev/null @@ -1,27 +0,0 @@ -package client - -import ( - "io/ioutil" - "os" - - "github.com/tendermint/go-amino" - - "github.com/cosmos/cosmos-sdk/x/auth" -) - -// Read and decode a StdTx from the given filename. Can pass "-" to read from stdin. -func ReadStdTxFromFile(cdc *amino.Codec, filename string) (stdTx auth.StdTx, err error) { - var bytes []byte - if filename == "-" { - bytes, err = ioutil.ReadAll(os.Stdin) - } else { - bytes, err = ioutil.ReadFile(filename) - } - if err != nil { - return - } - if err = cdc.UnmarshalJSON(bytes, &stdTx); err != nil { - return - } - return -} diff --git a/x/auth/client/util_test.go b/x/auth/client/util_test.go deleted file mode 100644 index 409219cd72..0000000000 --- a/x/auth/client/util_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package client - -import ( - "os" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test" - "github.com/cosmos/cosmos-sdk/codec" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/auth" -) - -func TestReadStdTxFromFile(t *testing.T) { - cdc := codec.New() - sdk.RegisterCodec(cdc) - - // Build a test transaction - fee := auth.NewStdFee(50000, sdk.Coins{sdk.NewInt64Coin("atom", 150)}) - stdTx := auth.NewStdTx([]sdk.Msg{}, fee, []auth.StdSignature{}, "foomemo") - - // Write it to the file - encodedTx, _ := cdc.MarshalJSON(stdTx) - jsonTxFile := clitest.WriteToNewTempFile(t, string(encodedTx)) - defer os.Remove(jsonTxFile.Name()) - - // Read it back - decodedTx, err := ReadStdTxFromFile(cdc, jsonTxFile.Name()) - require.Nil(t, err) - require.Equal(t, decodedTx.Memo, "foomemo") -}