Incorporating @ValarDragon's comments

This commit is contained in:
Alessio Treglia 2018-08-24 09:48:02 +01:00
parent fb5fe9914d
commit f36f749818
No known key found for this signature in database
GPG Key ID: E8A48AE5311D765A
6 changed files with 102 additions and 29 deletions

View File

@ -9,6 +9,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context" authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context"
amino "github.com/tendermint/go-amino" amino "github.com/tendermint/go-amino"
"github.com/tendermint/tendermint/libs/common"
) )
// DefaultGasAdjustment is applied to gas estimates to avoid tx // DefaultGasAdjustment is applied to gas estimates to avoid tx
@ -58,7 +59,7 @@ func SendTx(txCtx authctx.TxContext, cliCtx context.CLIContext, msgs []sdk.Msg)
return err return err
} }
txCtx, err = enrichCtxWithGasIfGasAuto(txCtx, cliCtx, cliCtx.FromAddressName, passphrase, msgs) txCtx, err = enrichCtxWithGasIfGasAuto(txCtx, cliCtx, passphrase, msgs)
if err != nil { if err != nil {
return err return err
} }
@ -72,35 +73,43 @@ func SendTx(txCtx authctx.TxContext, cliCtx context.CLIContext, msgs []sdk.Msg)
return cliCtx.EnsureBroadcastTx(txBytes) return cliCtx.EnsureBroadcastTx(txBytes)
} }
func enrichCtxWithGasIfGasAuto(txCtx authctx.TxContext, cliCtx context.CLIContext, name, passphrase string, msgs []sdk.Msg) (authctx.TxContext, error) { func enrichCtxWithGasIfGasAuto(txCtx authctx.TxContext, cliCtx context.CLIContext, passphrase string, msgs []sdk.Msg) (authctx.TxContext, error) {
if cliCtx.Gas == 0 { if cliCtx.Gas == 0 {
return EnrichTxContextWithGas(txCtx, cliCtx, name, passphrase, msgs) txBytes, err := BuildAndSignTxWithZeroGas(txCtx, cliCtx.FromAddressName, passphrase, msgs)
if err != nil {
return txCtx, err
}
estimate, adjusted, err := CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment)
if err != nil {
return txCtx, err
}
fmt.Fprintf(os.Stderr, "gas: [estimated = %v] [adjusted = %v]\n", estimate, adjusted)
return txCtx.WithGas(adjusted), nil
} }
return txCtx, nil return txCtx, nil
} }
// EnrichTxContextWithGas simulates the execution of a transaction to // BuildAndSignTxWithZeroGas builds transactions with GasWanted set to 0.
// then populate the relevant TxContext.Gas field with the estimate func BuildAndSignTxWithZeroGas(txCtx authctx.TxContext, name, passphrase string, msgs []sdk.Msg) ([]byte, error) {
// obtained by the query. return txCtx.WithGas(0).BuildAndSign(name, passphrase, msgs)
func EnrichTxContextWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name, passphrase string, msgs []sdk.Msg) (authctx.TxContext, error) { }
txCtxSimulation := txCtx.WithGas(0)
txBytes, err := txCtxSimulation.BuildAndSign(name, passphrase, msgs) // CalculateGas simulates the execution of a transaction and returns
if err != nil { // both the estimate obtained by the query and the adjusted amount.
return txCtx, err func CalculateGas(queryFunc func(string, common.HexBytes) ([]byte, error), cdc *amino.Codec, txBytes []byte, adjustment float64) (estimate, adjusted int64, err error) {
}
// run a simulation (via /app/simulate query) to // run a simulation (via /app/simulate query) to
// estimate gas and update TxContext accordingly // estimate gas and update TxContext accordingly
rawRes, err := cliCtx.Query("/app/simulate", txBytes) rawRes, err := queryFunc("/app/simulate", txBytes)
if err != nil { if err != nil {
return txCtx, err return
} }
estimate, err := parseQueryResponse(cliCtx.Codec, rawRes) estimate, err = parseQueryResponse(cdc, rawRes)
if err != nil { if err != nil {
return txCtx, err return
} }
adjusted := adjustGasEstimate(estimate, cliCtx.GasAdjustment) adjusted = adjustGasEstimate(estimate, adjustment)
fmt.Fprintf(os.Stderr, "gas: [estimated = %v] [adjusted = %v]\n", estimate, adjusted) fmt.Fprintf(os.Stderr, "gas: [estimated = %v] [adjusted = %v]\n", estimate, adjusted)
return txCtx.WithGas(adjusted), nil return
} }
func adjustGasEstimate(estimate int64, adjustment float64) int64 { func adjustGasEstimate(estimate int64, adjustment float64) int64 {

View File

@ -86,11 +86,12 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLICo
} }
if m.Gas == 0 { if m.Gas == 0 {
txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) newCtx, httperr, err := enrichContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, msg)
if err != nil { if err != nil {
utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error()) utils.WriteErrorResponse(&w, httperr, err.Error())
return return
} }
txCtx = newCtx
} }
txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg})
@ -114,3 +115,15 @@ func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLICo
w.Write(output) w.Write(output)
} }
} }
func enrichContextWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name, password string, msg sdk.Msg) (authctx.TxContext, int, error) {
txBytes, err := utils.BuildAndSignTxWithZeroGas(txCtx, name, password, []sdk.Msg{msg})
if err != nil {
return txCtx, http.StatusInternalServerError, err
}
_, adjusted, err := utils.CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment)
if err != nil {
return txCtx, http.StatusUnauthorized, err
}
return txCtx.WithGas(adjusted), http.StatusOK, nil
}

View File

@ -77,11 +77,12 @@ func signAndBuild(w http.ResponseWriter, cliCtx context.CLIContext, baseReq base
} }
if baseReq.Gas == 0 { if baseReq.Gas == 0 {
txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, baseReq.Name, baseReq.Password, []sdk.Msg{msg}) newCtx, httperr, err := enrichContextWithGas(txCtx, cliCtx, baseReq.Name, baseReq.Password, msg)
if err != nil { if err != nil {
utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error()) utils.WriteErrorResponse(&w, httperr, err.Error())
return return
} }
txCtx = newCtx
} }
txBytes, err := txCtx.BuildAndSign(baseReq.Name, baseReq.Password, []sdk.Msg{msg}) txBytes, err := txCtx.BuildAndSign(baseReq.Name, baseReq.Password, []sdk.Msg{msg})
if err != nil { if err != nil {
@ -115,3 +116,15 @@ func parseInt64OrReturnBadRequest(s string, w http.ResponseWriter) (n int64, ok
} }
return n, true return n, true
} }
func enrichContextWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name, password string, msg sdk.Msg) (authctx.TxContext, int, error) {
txBytes, err := utils.BuildAndSignTxWithZeroGas(txCtx, name, password, []sdk.Msg{msg})
if err != nil {
return txCtx, http.StatusInternalServerError, err
}
_, adjusted, err := utils.CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment)
if err != nil {
return txCtx, http.StatusUnauthorized, err
}
return txCtx.WithGas(adjusted), http.StatusOK, nil
}

View File

@ -77,12 +77,12 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.C
} }
if m.Gas == 0 { if m.Gas == 0 {
txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) newCtx, httperr, err := enrichContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, msg)
if err != nil { if err != nil {
w.WriteHeader(http.StatusUnauthorized) utils.WriteErrorResponse(&w, httperr, err.Error())
w.Write([]byte(err.Error()))
return return
} }
txCtx = newCtx
} }
txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg})
@ -106,3 +106,15 @@ func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.C
w.Write(output) w.Write(output)
} }
} }
func enrichContextWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name, password string, msg sdk.Msg) (authctx.TxContext, int, error) {
txBytes, err := utils.BuildAndSignTxWithZeroGas(txCtx, name, password, []sdk.Msg{msg})
if err != nil {
return txCtx, http.StatusInternalServerError, err
}
_, adjusted, err := utils.CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment)
if err != nil {
return txCtx, http.StatusUnauthorized, err
}
return txCtx.WithGas(adjusted), http.StatusOK, nil
}

View File

@ -78,11 +78,12 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI
msg := slashing.NewMsgUnjail(validatorAddr) msg := slashing.NewMsgUnjail(validatorAddr)
if m.Gas == 0 { if m.Gas == 0 {
txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) newCtx, httperr, err := enrichContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, msg)
if err != nil { if err != nil {
utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error()) utils.WriteErrorResponse(&w, httperr, err.Error())
return return
} }
txCtx = newCtx
} }
txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg})
@ -106,3 +107,15 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI
w.Write(output) w.Write(output)
} }
} }
func enrichContextWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name, password string, msg sdk.Msg) (authctx.TxContext, int, error) {
txBytes, err := utils.BuildAndSignTxWithZeroGas(txCtx, name, password, []sdk.Msg{msg})
if err != nil {
return txCtx, http.StatusInternalServerError, err
}
_, adjusted, err := utils.CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment)
if err != nil {
return txCtx, http.StatusUnauthorized, err
}
return txCtx.WithGas(adjusted), http.StatusOK, nil
}

View File

@ -276,11 +276,12 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex
m.Sequence++ m.Sequence++
if m.Gas == 0 { if m.Gas == 0 {
txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) newCtx, httperr, err := enrichContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, msg)
if err != nil { if err != nil {
utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error()) utils.WriteErrorResponse(&w, httperr, err.Error())
return return
} }
txCtx = newCtx
} }
txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg}) txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg})
@ -315,3 +316,15 @@ func delegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx contex
w.Write(output) w.Write(output)
} }
} }
func enrichContextWithGas(txCtx authcliCtx.TxContext, cliCtx context.CLIContext, name, password string, msg sdk.Msg) (authcliCtx.TxContext, int, error) {
txBytes, err := utils.BuildAndSignTxWithZeroGas(txCtx, name, password, []sdk.Msg{msg})
if err != nil {
return txCtx, http.StatusInternalServerError, err
}
_, adjusted, err := utils.CalculateGas(cliCtx.Query, cliCtx.Codec, txBytes, cliCtx.GasAdjustment)
if err != nil {
return txCtx, http.StatusUnauthorized, err
}
return txCtx.WithGas(adjusted), http.StatusOK, nil
}