-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Simulate transactions by default to set gas automatically #2047
Conversation
client/utils/utils.go
Outdated
// execution failures due to state changes that might | ||
// occur between the tx simulation and the actual run. | ||
const ( | ||
SimulateGasLimit = 200000 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be avoid by introducing a dry-run ante handler that, othen than simulating sig verification, would use an infinite gas meter as well.
Logged all calls to
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks; left a few comments. Can we also list the parts we're intentionally saving for a later PR (looks like skipping the signature check isn't in this yet?)
client/flags.go
Outdated
@@ -4,11 +4,14 @@ import "github.com/spf13/cobra" | |||
|
|||
// nolint | |||
const ( | |||
DefaultGasLimit = 200000 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need this at all? If the user doesn't want to simulate the transaction I think we should force them to manually specify gas.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, I will change it accordingly.
I was thinking to drop the --gas-auto
flag in favor of having --gas
value set to 0 by default, which would enable the auto gas feature.
client/utils/utils.go
Outdated
// execution failures due to state changes that might | ||
// occur between the tx simulation and the actual run. | ||
const ( | ||
SimulateGasLimit = 200000 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think a limit makes sense here either, can we use an InfiniteGasMeter
on simulation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed, please review
client/utils/utils.go
Outdated
// occur between the tx simulation and the actual run. | ||
const ( | ||
SimulateGasLimit = 200000 | ||
GasEstimateAdjustment = 1.2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be a CLI flag (1.2 is probably a fine default value)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about --gas-adjustment
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good
baseapp/baseapp.go
Outdated
@@ -575,6 +617,9 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk | |||
// determined by the GasMeter. We need access to the context to get the gas | |||
// meter so we initialize upfront. | |||
var gasWanted int64 | |||
if mode == runTxModeSimulate { | |||
return app.simulateTx(txBytes, tx) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm I'm not sure this is the optimal way to structure this function set, now there seems to be some duplicate code in simulateTx
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressing this now, expect a commit soon
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting the --gas flag value to 0 triggers a simulation of the tx before the actual execution
Could we change it to an independent flag (e.g --with-simulation
) so that the user can get information from the --help
command as well ?
Setting --gas=0
looks more like an easter egg to me... (specially if we lack the necessary documentation for the simulation)
@alessio left a review. If you still want to keep |
Users may be led to think that they could run a simulation with a custom
amount of gas by appending both `--with-simulation` and `--gas=$amount`.
Thus I'd rather document the special case `--gas=0`, considering that an
extra `--dry-run/--simulate` flag too will become available shortly.
…On Thu, 23 Aug 2018, 13:18 Federico Kunze, ***@***.***> wrote:
@alessio <https://github.com/alessio> left a review, if you still want to
keep --gas=0 logic, please add docs for it in the client section of the
SDK docs :)
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2047 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAN_7PXXGxomy9f1c07VhhxcUjPc5Xinks5uTp2RgaJpZM4V-cqW>
.
|
@alessio Ok, makes sense to me then. Please add the instructions on the documentation and |
ACKed and incorporated.
Thanks
…On Thu, Aug 23, 2018 at 1:33 PM, Federico Kunze ***@***.***> wrote:
@alessio <https://github.com/alessio> Ok, makes sense to me then. Please
add the instructions on the documentation and --gas flag as well. Then
you can dismiss my review and I'll approve your PR
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2047 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAN_7ADjNgB671ucnQMdQtaGhQoGS7zeks5uTqEngaJpZM4V-cqW>
.
--
Alessio Treglia | alessio@tendermint.com
0416 0004 A827 6E40 BB98 90FB E8A4 8AE5 311D 765A
|
client/utils/utils_test.go
Outdated
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func Test_parseQueryResponse(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename to TestParseQueryResponse
It was automatically generated by VSCode. Happy to amend it though
…On Thu, 23 Aug 2018, 19:08 Federico Kunze, ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In client/utils/utils_test.go
<#2047 (comment)>:
> @@ -0,0 +1,20 @@
+package utils
+
+import (
+ "testing"
+
+ "github.com/cosmos/cosmos-sdk/cmd/gaia/app"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+ "github.com/stretchr/testify/assert"
+)
+
+func Test_parseQueryResponse(t *testing.T) {
Rename to TestParseQueryResponse
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2047 (review)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAN_7E_O2-U7eur0W-nrXS89KTeJKoPqks5uTu-ygaJpZM4V-cqW>
.
|
cmd/gaia/cli_test/cli_test.go
Outdated
@@ -277,10 +286,29 @@ func getTestingHomeDirs() (string, string) { | |||
return gaiadHome, gaiacliHome | |||
} | |||
|
|||
func initialiseFixtures(t *testing.T) (chainID, servAddr, port string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo here initialize
@@ -97,6 +97,11 @@ gaiacli send \ | |||
The `--amount` flag accepts the format `--amount=<value|coin_name>`. | |||
::: | |||
|
|||
::: tip Note | |||
You may want to cap the maximum gas that can be consumed by the transaction via the `--gas` flag. | |||
If set to 0, the gas limit will be automatically estimated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we need to add the --gas-adjustement
flag as well ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Screw British English, happy to amend it
…On Thu, 23 Aug 2018, 19:10 Federico Kunze, ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In cmd/gaia/cli_test/cli_test.go
<#2047 (comment)>:
> @@ -277,10 +286,29 @@ func getTestingHomeDirs() (string, string) {
return gaiadHome, gaiacliHome
}
+func initialiseFixtures(t *testing.T) (chainID, servAddr, port string) {
typo here initiali*z*e
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2047 (review)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAN_7BR-xZ9TKm7KUnIUToqx2vL2x4nBks5uTvAYgaJpZM4V-cqW>
.
|
x/bank/client/rest/sendtx.go
Outdated
return | ||
} | ||
|
||
w.Write(output) | ||
} | ||
} | ||
|
||
func writeErr(w *http.ResponseWriter, status int, msg string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool ! could we move this to another pkg and export it ?
x/ibc/client/rest/transfer.go
Outdated
if m.Gas == 0 { | ||
txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) | ||
if err != nil { | ||
w.WriteHeader(http.StatusUnauthorized) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use your writeErr
function
x/slashing/client/rest/tx.go
Outdated
if m.Gas == 0 { | ||
txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) | ||
if err != nil { | ||
w.WriteHeader(http.StatusUnauthorized) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use writeErr
x/stake/client/rest/tx.go
Outdated
if m.Gas == 0 { | ||
txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg}) | ||
if err != nil { | ||
w.WriteHeader(http.StatusUnauthorized) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK. Left a few comments but LGTM ! Thanks @alessio !
Refactored into `github.com/cosmos/cosmos-sdk/x/gov/client/rest/util.WriteErrorResponse`
…On Thu, Aug 23, 2018 at 7:17 PM, Federico Kunze ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In x/slashing/client/rest/tx.go
<#2047 (comment)>:
> @@ -81,6 +82,15 @@ func unjailRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLI
msg := slashing.NewMsgUnjail(validatorAddr)
+ if m.Gas == 0 {
+ txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, m.LocalAccountName, m.Password, []sdk.Msg{msg})
+ if err != nil {
+ w.WriteHeader(http.StatusUnauthorized)
use writeErr
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2047 (review)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAN_7O6AUTpHWI4Y8x0WSltZtYaiFMrQks5uTvGkgaJpZM4V-cqW>
.
--
Alessio Treglia | alessio@tendermint.com
0416 0004 A827 6E40 BB98 90FB E8A4 8AE5 311D 765A
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets move the write header stuff / error stuff into a seperate PR. Its easier to review code if the refactors are seperated from actual code changes. Also some of the cases with gas = 0 checks seem unclear to me.
baseapp/baseapp.go
Outdated
@@ -495,13 +495,11 @@ func validateBasicTxMsgs(msgs []sdk.Msg) sdk.Error { | |||
|
|||
func (app *BaseApp) getContextForAnte(mode runTxMode, txBytes []byte) (ctx sdk.Context) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets add some comment here about what the intended result of this is under each mode.
I agree with the code change, however this code is hard to grok, especially now that we've removed the reference to check/simulate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorporated, thanks
baseapp/baseapp.go
Outdated
@@ -567,6 +565,13 @@ func getState(app *BaseApp, mode runTxMode) *state { | |||
return app.deliverState | |||
} | |||
|
|||
func (app *BaseApp) applyTxMode(ctx sdk.Context, mode runTxMode) sdk.Context { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this called applyTxMode
if it only does stuff for simulate? It seems confusing imo to generalize this when there is only one case. We're also not really applying the tx mode imo, its just initializing the context.
Perhaps rename this to initializeTxMode
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about initializeContext()
?
client/flags.go
Outdated
@@ -49,7 +52,8 @@ func PostCommands(cmds ...*cobra.Command) []*cobra.Command { | |||
c.Flags().String(FlagChainID, "", "Chain ID of tendermint node") | |||
c.Flags().String(FlagNode, "tcp://localhost:26657", "<host>:<port> to tendermint rpc interface for this chain") | |||
c.Flags().Bool(FlagUseLedger, false, "Use a connected Ledger device") | |||
c.Flags().Int64(FlagGas, 200000, "gas limit to set per-transaction") | |||
c.Flags().Int64(FlagGas, 0, "gas limit to set per-transaction; set to 0 to calculate required gas automatically") | |||
c.Flags().Float64(FlagGasAdjustment, DefaultGasAdjustment, "gas adjustment to be applied on the estimate returned by the tx simulation") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps indicate that this is a multiplicative factor being multiplied against the estimate (vs additive).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK'd
@@ -263,6 +263,10 @@ func TestCoinSend(t *testing.T) { | |||
|
|||
require.Equal(t, "steak", mycoins.Denom) | |||
require.Equal(t, int64(1), mycoins.Amount.Int64()) | |||
|
|||
// test failure with too little gas |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets test success with sufficient, manually specified gas as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACKd
client/lcd/lcd_test.go
Outdated
"sequence":"%d", | ||
"amount":[%s], | ||
"chain_id":"%s", | ||
"gas":"%v" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can eliminate some of the code duplication here by just making the line "gas":"%v" a fmt string arg, and just set that at the top, and pass that in. (so if gas > 0, that argument would be set to
"gas":"\n", otherwise it would be set to "".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACKd
::: tip Note | ||
You may want to cap the maximum gas that can be consumed by the transaction via the `--gas` flag. | ||
If set to 0, the gas limit will be automatically estimated. | ||
Gas estimate might be inaccurate as state changes could occur in between the end of the simulation and the actual execution of a transaction, thus an adjustment is applied on top of the original estimate in order to ensure the transaction is broadcasted successfully. The adjustment can be controlled via the `--gas-adjustment` flag, whose default value is 1.2. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we write up into an issue to make this configurable per tx type in a config somewhere? The reason for considering it would be that a bank send tx probably is going to be most common tx, and also shouldn't have an increased cost due to other state changes, so it shouldn't have the same adjustment as staking txs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Please fork it into a new issue 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is definitely something to consider because the user pays for the allocated gas, not the consumed gas.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
x/auth/ante.go
Outdated
@@ -35,7 +35,11 @@ func NewAnteHandler(am AccountMapper, fck FeeCollectionKeeper) sdk.AnteHandler { | |||
} | |||
|
|||
// set the gas meter | |||
newCtx = ctx.WithGasMeter(sdk.NewGasMeter(stdTx.Fee.Gas)) | |||
if stdTx.Fee.Gas == 0 { | |||
newCtx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this here? Using an infinite gas meter here seems odd to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When running in simulation mode, we want no gas capping whatsoever - CC'ing @cwgoes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need to cap gas in a simulation, we just need to measure it - is there a reason you think we would need to cap it @ValarDragon?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like switching on gas equals 0. This feels like it could cause more bugs / increase the attack surface. I think we should find another way of communicating that were in simulation mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could it not be set in the context somewhere upstream?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if we use a default gas limit (some sort of sane default, e.g. 200000
- which is the current default value) and switch back to use a capped GasMeter
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re:
simulations shouldn't be verifying signatures
That too is tricky. Simulations go through the query interface, which requires messages to be signed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That still doesn't really alleviate my concern. (That does limit the situation though)
I do think switching on 0 gas is less safe, as we now have to make sure that a tx on the network with 0 gas is stopped before getting to this line. Its prefferrable to just have a separate method to flag simulations, and have the normal gas logic prevent a 0 gas tx imo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you reckon the following could mitigate the risk?
diff --git a/client/utils/utils.go b/client/utils/utils.go
index fb5d6198..49258b86 100644
--- a/client/utils/utils.go
+++ b/client/utils/utils.go
@@ -1,6 +1,7 @@
package utils
import (
+ "errors"
"fmt"
"os"
@@ -108,6 +109,10 @@ func CalculateGas(queryFunc func(string, common.HexBytes) ([]byte, error), cdc *
if err != nil {
return
}
+ if estimate <= 0 {
+ err = errors.New("simulation returned gas=0")
+ return
+ }
adjusted = adjustGasEstimate(estimate, adjustment)
fmt.Fprintf(os.Stderr, "gas: [estimated = %v] [adjusted = %v]\n", estimate, adjusted)
return
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'm not conveying my concern well. This doesn't really alleviate it.
Right now the current code is saying "If tx.fee.Gas = 0, I get infinite gas". I think this is a bad design for it, even if we add checks in other places. As now were opening more holes, where are a complex series of conditionals could lead to this gas=0, get infinite gas, or a change may happen later that forgets that this could be the case. Instead we should signal directly that we want simulation mode, so this is no longer a fear. (As a tx itself cannot signal simulation mode, so theres no safety risk there)
I agree that this isn't a simple change, but I think its necessary for this to go through. I also think requiring that simulation not take in the private key / a signature is necessary, even if it requires another AnteHandler constructor. You don't want to increase the amount of things a private key has to sign / increase the amount of exposure a private key has if you don't have to.
x/auth/ante_test.go
Outdated
@@ -360,7 +360,7 @@ func TestAnteHandlerMemoGas(t *testing.T) { | |||
var tx sdk.Tx | |||
msg := newTestMsg(addr1) | |||
privs, accnums, seqs := []crypto.PrivKey{priv1}, []int64{0}, []int64{0} | |||
fee := NewStdFee(0, sdk.NewInt64Coin("atom", 0)) | |||
fee := NewStdFee(1, sdk.NewInt64Coin("atom", 0)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't 0 be used for the fee here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0
gas triggers the simulation
@@ -32,15 +33,13 @@ func QueryAccountRequestHandlerFn( | |||
|
|||
addr, err := sdk.AccAddressFromBech32(bech32addr) | |||
if err != nil { | |||
w.WriteHeader(http.StatusBadRequest) | |||
w.Write([]byte(err.Error())) | |||
utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets move this refactor into a seperate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
requested by @fedekunze - I'd keep it if you don't mind as IMHO it does more good than bad
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yet I'll refrain in future to tackle technical debt while working on a specific issue 👍
x/gov/client/rest/util.go
Outdated
@@ -82,21 +76,28 @@ func signAndBuild(w http.ResponseWriter, cliCtx context.CLIContext, baseReq base | |||
Gas: baseReq.Gas, | |||
} | |||
|
|||
if baseReq.Gas == 0 { | |||
txCtx, err = utils.EnrichTxContextWithGas(txCtx, cliCtx, baseReq.Name, baseReq.Password, []sdk.Msg{msg}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EnrichTxContextWithGas feels like an odd name for whats happening here. I think it should be renamed to use the word Calculate
. Also this should be refactored to not depend on the password imo. (We should not increase the surface area that gets password access) We can charge gas purely on signature type. (As simulation shouldn't spend the signature verification time anyway)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about the following?
// BuildAndSignTxWithZeroGas builds transactions with GasWanted set to 0.
func BuildAndSignTxWithZeroGas(txCtx authctx.TxContext, name, passphrase string, msgs []sdk.Msg) ([]byte, error) {
return txCtx.WithGas(0).BuildAndSign(name, passphrase, msgs)
}
// EnrichTxContextWithGas simulates the execution of a transaction to
// then populate the relevant TxContext.Gas field with the estimate
// obtained by the query.
func EnrichTxContextWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, txBytes []byte) (authctx.TxContext, error) {
// run a simulation (via /app/simulate query) to
// estimate gas and update TxContext accordingly
rawRes, err := cliCtx.Query("/app/simulate", txBytes)
if err != nil {
return txCtx, err
}
estimate, err := parseQueryResponse(cliCtx.Codec, rawRes)
if err != nil {
return txCtx, err
}
adjusted := adjustGasEstimate(estimate, cliCtx.GasAdjustment)
fmt.Fprintf(os.Stderr, "gas: [estimated = %v] [adjusted = %v]\n", estimate, adjusted)
return txCtx.WithGas(adjusted), nil
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I disagree with needing a signature here. We don't want simulations to depend on the private key. (Extra computation time, inconvenience, etc. Especially if your signing from a ledger)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few questions/comments.
baseapp/baseapp.go
Outdated
@@ -567,6 +567,13 @@ func getState(app *BaseApp, mode runTxMode) *state { | |||
return app.deliverState | |||
} | |||
|
|||
func (app *BaseApp) initializeContext(ctx sdk.Context, mode runTxMode) sdk.Context { | |||
if mode != runTxModeSimulate { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(nit) Writing this with an if mode == runTxModeSimulate
is a bit more obvious (that we're doing something special for simulation).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorporated, thanks.
baseapp/baseapp.go
Outdated
ctx = app.deliverState.ctx.WithTxBytes(txBytes) | ||
ctx = ctx.WithSigningValidators(app.signedValidators) | ||
ctx = getState(app, mode).ctx.WithTxBytes(txBytes) | ||
if mode != runTxModeDeliver { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(nit) Writing this with if mode == runTxModeDelvier
is a bit more obvious (that we're doing something special for delivertx)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorporated, thanks
client/flags.go
Outdated
@@ -4,11 +4,14 @@ import "github.com/spf13/cobra" | |||
|
|||
// nolint | |||
const ( | |||
DefaultGasAdjustment = 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought this was 1.2 (below)?
client/utils/utils.go
Outdated
// broadcast to a Tendermint node | ||
return cliCtx.EnsureBroadcastTx(txBytes) | ||
} | ||
|
||
func enrichCtxWithGasIfGasAuto(txCtx authctx.TxContext, cliCtx context.CLIContext, passphrase string, msgs []sdk.Msg) (authctx.TxContext, error) { | ||
if cliCtx.Gas == 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be slightly clearer to put this conditional outside of the function, and only call the function if cliCtx.Gas == 0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As long as linter doesn't complain yes, that was my intent
::: tip Note | ||
You may want to cap the maximum gas that can be consumed by the transaction via the `--gas` flag. | ||
If set to 0, the gas limit will be automatically estimated. | ||
Gas estimate might be inaccurate as state changes could occur in between the end of the simulation and the actual execution of a transaction, thus an adjustment is applied on top of the original estimate in order to ensure the transaction is broadcasted successfully. The adjustment can be controlled via the `--gas-adjustment` flag, whose default value is 1.2. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is definitely something to consider because the user pays for the allocated gas, not the consumed gas.
x/gov/client/rest/util.go
Outdated
@@ -114,3 +116,15 @@ func parseInt64OrReturnBadRequest(s string, w http.ResponseWriter) (n int64, ok | |||
} | |||
return n, true | |||
} | |||
|
|||
func enrichContextWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name, password string, msg sdk.Msg) (authctx.TxContext, int, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we deduplicate this function (put it in a common file)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dedup'd, though left it there for now if that is OK for you
x/ibc/client/rest/transfer.go
Outdated
return | ||
} | ||
|
||
w.Write(output) | ||
} | ||
} | ||
|
||
func enrichContextWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name, password string, msg sdk.Msg) (authctx.TxContext, int, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we deduplicate this function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactored, it now uses utils.EnrichCtxWithGas()
x/slashing/client/rest/tx.go
Outdated
return | ||
} | ||
|
||
w.Write(output) | ||
} | ||
} | ||
|
||
func enrichContextWithGas(txCtx authctx.TxContext, cliCtx context.CLIContext, name, password string, msg sdk.Msg) (authctx.TxContext, int, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we deduplicate this function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
x/stake/client/rest/tx.go
Outdated
return | ||
} | ||
|
||
w.Write(output) | ||
} | ||
} | ||
|
||
func enrichContextWithGas(txCtx authcliCtx.TxContext, cliCtx context.CLIContext, name, password string, msg sdk.Msg) (authcliCtx.TxContext, int, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we deduplicate this function? This really shouldn't need to be in the module-specific REST files anyways I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
Huh -- looks like |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK, thanks @alessio!
Try merging develop, might fix CI.
Just realized one of my comments was hidden, so I'll repost down here: I disagree with needing a signature / passphrase in the simulation. We don't want simulations to depend on the private key. (Extra computation time for signing / verifying, inconvenience, etc. Especially if your signing from a ledger) |
I think we're agreed on this, but it was a point for a future PR (@alessio ?) |
Correct
…On Fri, Aug 24, 2018 at 5:41 PM, Christopher Goes ***@***.***> wrote:
I disagree with needing a signature / passphrase in the simulation. We
don't want simulations to depend on the private key. (Extra computation
time for signing / verifying, inconvenience, etc. Especially if your
signing from a ledger)
I think we're agreed on this, but it was a point for a future PR ***@***.***
<https://github.com/alessio> ?)
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2047 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAN_7GTr_jAGzPEfrigomgx_esNtk9W4ks5uUCzJgaJpZM4V-cqW>
.
--
Alessio Treglia | alessio@tendermint.com
0416 0004 A827 6E40 BB98 90FB E8A4 8AE5 311D 765A
|
I think that is something that should absolutely be prelaunch. I'm opposed to having us have private keys create signatures they don't have to. (There are many classes of sidechannel attacks, and they all only get more feasible the more signature / msg pairs you have) I'm fine with merging this without that then, though I really would prefer that being done here. I do think the |
If we're going to merge this without removing the privkey dependency in simulation, lets make the default not to simulate, and only switch the default once we fix this. I really dislike the idea of having every client signing an extra message, just because thats unnecessary side channel leakage for something that could have tons of money behind it. (I fear we may forget to fix this prelaunch / decide to punt to postlaunch for quicker launch) |
It's easy to skip sig verification or replace |
I'm suggesting just have the public key. The AnteHandler determines verification gas cost from just the pubkey. https://github.com/cosmos/cosmos-sdk/blob/develop/x/auth/ante.go#L202 The pubkey is derived from the account in the message. Account validation is independent of knowledge of private key as well. I think having an alternate Simulation AnteHandler would be preferrable though than conditionals on simulation mode, but conditions on simulation mode are safe as long as simulation mode can never be set from information inside of the tx. |
gaia's GenesisAccounts don't have public keys, and many test cases use
genesis accounts to perform ops:
// GenesisAccount doesn't need pubkey or sequence
type GenesisAccount struct {
Address sdk.AccAddress `json:"address"`
Coins sdk.Coins `json:"coins"`
}
I'm on it though.
…On Sat, Aug 25, 2018 at 7:00 PM, Dev Ojha ***@***.***> wrote:
I'm suggesting just have the public key. The AnteHandler determines
verification gas cost from just the pubkey. https://github.com/cosmos/
cosmos-sdk/blob/develop/x/auth/ante.go#L202
The pubkey is derived from the account in the message iirc.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2047 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAN_7L79tdMB5NShuWAzChEMXKL-Jrivks5uUZCwgaJpZM4V-cqW>
.
--
Alessio Treglia | alessio@tendermint.com
0416 0004 A827 6E40 BB98 90FB E8A4 8AE5 311D 765A
|
I am aware of that. Yet no signature, no public key is attached to the tx. |
In those cases the pubkey is supplied in the tx. I agree with inclusion of pubkey when necessary, I'm only opposed to calculation of a signature on a message you don't want broadcasted, and privkey dependency. |
This can be saved for later pr, I just don't think simulation should be default until this is done though. |
Don't get me wrong, I believe you've got quite a point, yet txs need to be enriched with more information re: keys the msgs will be signed with to go through a simulation which could lead to potentially helpful gas estimates. And REST endpoints too are in scope here, therefore passing information via |
This cannot be the case. Unlike Ethereum, we don't do pubkey recovery, so in order to ever have the pubkey, it must have been explicitly provided.
I don't really understand what your suggesting here. The simulation fundamentally requires no dependency on the private key, or the signature. The gas cost relating to the signature is determined from the pubkey type. (Signatures are just []byte now, they no longer have types) I agree CLIContext doesn't make sense here. As @alexanderbez suggested here, we should be able to use the normal context to carry information about "are we in simulation mode". (Note this refers to sdk.Context, not the CLIContext. The number of contexts is confusing) For purposes of this PR, I think making simulation non-default suffices. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
I'll write up making simulation independent of the private key in another issue.
I think refactoring the API to put simulation mode in context
would be more ideal. We can definitely handle that in a separate issue / postlaunch though.
Good dialogue here folks! Yes, indeed, I was referring to the application's |
Thanks @alessio - if we could get that future PR with no-sign simulation in before 0.25, that would be 💯. |
I don't understand the push for this to be prelaunch, let alone next release. (Note this contradicts what I said earlier, but upon further thought I think it can be postlaunch) Its a nice to have (and a really cool thing at that), but something we can roll out in a non-breaking manner. The more features we keep trying to add prelaunch that aren't necessary, the longer it will take to launch. |
I think it will be very hard for users to estimate gas otherwise, and since we charge for gas allocated, not gas used, estimating gas is pretty essential. If there's another way to address that concern, open to it! |
* Add v9 changelog * Update changelog
Relevant issue: #1246
--gas=0
semantic in order to enable gas auto estimate.--gas-adjustment
flag.Closes: #1246
docs/
)PENDING.md
that include links to the relevant issue or PR that most accurately describes the change.cmd/gaia
andexamples/
For Admin Use: