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: Allow Simulation and Gen Only in REST Client #3467

Merged
merged 7 commits into from
Feb 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ IMPROVEMENTS
* Automatic account number and sequence population when fields are omitted
* Generate only functionality no longer requires access to a local Keybase
* `from` field in the `base_req` body can be a Keybase name or account address
* [\#3423](https://github.com/cosmos/cosmos-sdk/issues/3423) Allow simulation
(auto gas) to work with generate only.

* Gaia CLI (`gaiacli`)

Expand Down
9 changes: 9 additions & 0 deletions client/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package client

import "errors"

// common errors for CLI and REST clients
var (
ErrInvalidGasAdjustment = errors.New("invalid gas adjustment")
ErrInvalidSigner = errors.New("tx intended signer does not match the given signer")
)
24 changes: 20 additions & 4 deletions client/utils/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,11 +246,11 @@ func CompleteAndBroadcastTxREST(

if baseReq.Simulate || simAndExec {
if gasAdj < 0 {
WriteErrorResponse(w, http.StatusBadRequest, "gas adjustment must be a positive float")
WriteErrorResponse(w, http.StatusBadRequest, client.ErrInvalidGasAdjustment.Error())
return
}

txBldr, err = EnrichWithGas(txBldr, cliCtx, cliCtx.GetFromName(), msgs)
txBldr, err = EnrichWithGas(txBldr, cliCtx, msgs)
if err != nil {
WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
Expand Down Expand Up @@ -308,13 +308,16 @@ func PostProcessResponse(w http.ResponseWriter, cdc *codec.Codec, response inter
}

// WriteGenerateStdTxResponse writes response for the generate only mode.
func WriteGenerateStdTxResponse(w http.ResponseWriter, cdc *codec.Codec, br BaseReq, msgs []sdk.Msg) {
func WriteGenerateStdTxResponse(
w http.ResponseWriter, cdc *codec.Codec, cliCtx context.CLIContext, br BaseReq, msgs []sdk.Msg,
) {

gasAdj, ok := ParseFloat64OrReturnBadRequest(w, br.GasAdjustment, client.DefaultGasAdjustment)
if !ok {
return
}

_, gas, err := client.ParseGas(br.Gas)
simAndExec, gas, err := client.ParseGas(br.Gas)
if err != nil {
WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
Expand All @@ -325,6 +328,19 @@ func WriteGenerateStdTxResponse(w http.ResponseWriter, cdc *codec.Codec, br Base
br.Simulate, br.ChainID, br.Memo, br.Fees, br.GasPrices,
)

if simAndExec {
if gasAdj < 0 {
WriteErrorResponse(w, http.StatusBadRequest, client.ErrInvalidGasAdjustment.Error())
return
}

txBldr, err = EnrichWithGas(txBldr, cliCtx, msgs)
if err != nil {
WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
}

stdMsg, err := txBldr.Build(msgs)
if err != nil {
WriteErrorResponse(w, http.StatusBadRequest, err.Error())
Expand Down
27 changes: 12 additions & 15 deletions client/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io"
"os"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"

"github.com/tendermint/go-amino"
Expand All @@ -31,10 +32,10 @@ func CompleteAndBroadcastTxCLI(txBldr authtxb.TxBuilder, cliCtx context.CLIConte
return err
}

name := cliCtx.GetFromName()
fromName := cliCtx.GetFromName()

if txBldr.GetSimulateAndExecute() || cliCtx.Simulate {
txBldr, err = EnrichWithGas(txBldr, cliCtx, name, msgs)
txBldr, err = EnrichWithGas(txBldr, cliCtx, msgs)
if err != nil {
return err
}
Expand All @@ -44,13 +45,13 @@ func CompleteAndBroadcastTxCLI(txBldr authtxb.TxBuilder, cliCtx context.CLIConte
return nil
}

passphrase, err := keys.GetPassphrase(name)
passphrase, err := keys.GetPassphrase(fromName)
if err != nil {
return err
}

// build and sign the transaction
txBytes, err := txBldr.BuildAndSign(name, passphrase, msgs)
txBytes, err := txBldr.BuildAndSign(fromName, passphrase, msgs)
if err != nil {
return err
}
Expand All @@ -62,8 +63,8 @@ func CompleteAndBroadcastTxCLI(txBldr authtxb.TxBuilder, cliCtx context.CLIConte

// EnrichWithGas calculates the gas estimate that would be consumed by the
// transaction and set the transaction's respective value accordingly.
func EnrichWithGas(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (authtxb.TxBuilder, error) {
_, adjusted, err := simulateMsgs(txBldr, cliCtx, name, msgs)
func EnrichWithGas(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (authtxb.TxBuilder, error) {
_, adjusted, err := simulateMsgs(txBldr, cliCtx, msgs)
if err != nil {
return txBldr, err
}
Expand Down Expand Up @@ -126,8 +127,7 @@ func SignStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string,

// check whether the address is a signer
if !isTxSigner(sdk.AccAddress(addr), stdTx.GetSigners()) {
return signedStdTx, fmt.Errorf(
"The generated transaction's intended signer does not match the given signer: %q", name)
return signedStdTx, fmt.Errorf("%s: %s", client.ErrInvalidSigner, name)
}

if !offline {
Expand Down Expand Up @@ -155,8 +155,7 @@ func SignStdTxWithSignerAddress(txBldr authtxb.TxBuilder, cliCtx context.CLICont

// check whether the address is a signer
if !isTxSigner(addr, stdTx.GetSigners()) {
return signedStdTx, fmt.Errorf(
"The generated transaction's intended signer does not match the given signer: %q", name)
return signedStdTx, fmt.Errorf("%s: %s", client.ErrInvalidSigner, name)
}

if !offline {
Expand Down Expand Up @@ -207,8 +206,8 @@ func GetTxEncoder(cdc *codec.Codec) (encoder sdk.TxEncoder) {

// nolint
// SimulateMsgs simulates the transaction and returns the gas estimate and the adjusted value.
func simulateMsgs(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (estimated, adjusted uint64, err error) {
txBytes, err := txBldr.BuildWithPubKey(name, msgs)
func simulateMsgs(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (estimated, adjusted uint64, err error) {
txBytes, err := txBldr.BuildTxForSim(msgs)
if err != nil {
return
}
Expand Down Expand Up @@ -269,9 +268,7 @@ func buildUnsignedStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msg

func buildUnsignedStdTxOffline(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (stdTx auth.StdTx, err error) {
if txBldr.GetSimulateAndExecute() {
name := cliCtx.GetFromName()

txBldr, err = EnrichWithGas(txBldr, cliCtx, name, msgs)
txBldr, err = EnrichWithGas(txBldr, cliCtx, msgs)
if err != nil {
return
}
Expand Down
9 changes: 0 additions & 9 deletions docs/gaia/gaiacli.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,15 +233,6 @@ gaiacli tx send \
--generate-only > unsignedSendTx.json
```

::: tip Note
Simulation cannot be used in conjunction with tx generation only functionality
due to the fact that simulation requires a public key and generation only does
not utilize a Keybase.

You can now sign the transaction file generated through the `--generate-only`
flag by providing your key to the following command:
:::

```bash
gaiacli tx sign \
--chain-id=<chain_id> \
Expand Down
30 changes: 9 additions & 21 deletions x/auth/client/txbuilder/txbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ func (bldr TxBuilder) WithAccountNumber(accnum uint64) TxBuilder {

// Build builds a single message to be signed from a TxBuilder given a set of
// messages. It returns an error if a fee is supplied but cannot be parsed.
//
// TODO: Should consider renaming to BuildSignMsg.
func (bldr TxBuilder) Build(msgs []sdk.Msg) (StdSignMsg, error) {
chainID := bldr.chainID
if chainID == "" {
Expand Down Expand Up @@ -212,31 +214,17 @@ func (bldr TxBuilder) BuildAndSign(name, passphrase string, msgs []sdk.Msg) ([]b
return bldr.Sign(name, passphrase, msg)
}

// BuildWithPubKey builds a single message to be signed from a TxBuilder given a set of
// messages and attach the public key associated to the given name.
// It returns an error if a fee is supplied but cannot be parsed or the key cannot be
// retrieved.
func (bldr TxBuilder) BuildWithPubKey(name string, msgs []sdk.Msg) ([]byte, error) {
msg, err := bldr.Build(msgs)
if err != nil {
return nil, err
}

keybase, err := keys.GetKeyBase()
// BuildTxForSim creates a StdSignMsg and encodes a transaction with the
// StdSignMsg with a single empty StdSignature for tx simulation.
func (bldr TxBuilder) BuildTxForSim(msgs []sdk.Msg) ([]byte, error) {
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
signMsg, err := bldr.Build(msgs)
if err != nil {
return nil, err
}

info, err := keybase.Get(name)
if err != nil {
return nil, err
}

sigs := []auth.StdSignature{{
PubKey: info.GetPubKey(),
}}

return bldr.txEncoder(auth.NewStdTx(msg.Msgs, msg.Fee, sigs, msg.Memo))
// the ante handler will populate with a sentinel pubkey
sigs := []auth.StdSignature{{}}
return bldr.txEncoder(auth.NewStdTx(signMsg.Msgs, signMsg.Fee, sigs, signMsg.Memo))
}

// SignStdTx appends a signature to a StdTx and returns a copy of a it. If append
Expand Down
2 changes: 1 addition & 1 deletion x/bank/client/rest/sendtx.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func SendRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CLIC
}

msg := bankclient.CreateMsg(fromAddr, toAddr, req.Amount)
utils.WriteGenerateStdTxResponse(w, cdc, req.BaseReq, []sdk.Msg{msg})
utils.WriteGenerateStdTxResponse(w, cdc, cliCtx, req.BaseReq, []sdk.Msg{msg})
return
}

Expand Down
6 changes: 3 additions & 3 deletions x/gov/client/rest/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func postProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Han
}

if req.BaseReq.GenerateOnly {
utils.WriteGenerateStdTxResponse(w, cdc, req.BaseReq, []sdk.Msg{msg})
utils.WriteGenerateStdTxResponse(w, cdc, cliCtx, req.BaseReq, []sdk.Msg{msg})
return
}

Expand Down Expand Up @@ -146,7 +146,7 @@ func depositHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerF
}

if req.BaseReq.GenerateOnly {
utils.WriteGenerateStdTxResponse(w, cdc, req.BaseReq, []sdk.Msg{msg})
utils.WriteGenerateStdTxResponse(w, cdc, cliCtx, req.BaseReq, []sdk.Msg{msg})
return
}

Expand Down Expand Up @@ -196,7 +196,7 @@ func voteHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc
}

if req.BaseReq.GenerateOnly {
utils.WriteGenerateStdTxResponse(w, cdc, req.BaseReq, []sdk.Msg{msg})
utils.WriteGenerateStdTxResponse(w, cdc, cliCtx, req.BaseReq, []sdk.Msg{msg})
return
}

Expand Down
2 changes: 1 addition & 1 deletion x/ibc/client/rest/transfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func TransferRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.
msg := ibc.IBCTransferMsg{IBCPacket: packet}

if req.BaseReq.GenerateOnly {
utils.WriteGenerateStdTxResponse(w, cdc, req.BaseReq, []sdk.Msg{msg})
utils.WriteGenerateStdTxResponse(w, cdc, cliCtx, req.BaseReq, []sdk.Msg{msg})
return
}

Expand Down
2 changes: 1 addition & 1 deletion x/slashing/client/rest/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func unjailRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CL
}

if req.BaseReq.GenerateOnly {
utils.WriteGenerateStdTxResponse(w, cdc, req.BaseReq, []sdk.Msg{msg})
utils.WriteGenerateStdTxResponse(w, cdc, cliCtx, req.BaseReq, []sdk.Msg{msg})
return
}

Expand Down
6 changes: 3 additions & 3 deletions x/staking/client/rest/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func postDelegationsHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.
}

if req.BaseReq.GenerateOnly {
utils.WriteGenerateStdTxResponse(w, cdc, req.BaseReq, []sdk.Msg{msg})
utils.WriteGenerateStdTxResponse(w, cdc, cliCtx, req.BaseReq, []sdk.Msg{msg})
return
}

Expand Down Expand Up @@ -121,7 +121,7 @@ func postRedelegationsHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx contex
}

if req.BaseReq.GenerateOnly {
utils.WriteGenerateStdTxResponse(w, cdc, req.BaseReq, []sdk.Msg{msg})
utils.WriteGenerateStdTxResponse(w, cdc, cliCtx, req.BaseReq, []sdk.Msg{msg})
return
}

Expand Down Expand Up @@ -166,7 +166,7 @@ func postUnbondingDelegationsHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx
}

if req.BaseReq.GenerateOnly {
utils.WriteGenerateStdTxResponse(w, cdc, req.BaseReq, []sdk.Msg{msg})
utils.WriteGenerateStdTxResponse(w, cdc, cliCtx, req.BaseReq, []sdk.Msg{msg})
return
}

Expand Down