-
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
Gas management, estimation, limitation #963
Conversation
5dadbed
to
d1e2465
Compare
Codecov Report
@@ Coverage Diff @@
## develop #963 +/- ##
===========================================
+ Coverage 60.28% 60.73% +0.44%
===========================================
Files 74 75 +1
Lines 3591 3716 +125
===========================================
+ Hits 2165 2257 +92
- Misses 1256 1288 +32
- Partials 170 171 +1 |
Basic gas accounting implemented. Module structure could be cleaned up a bit. Currently gas costs are fixed constants in files, probably should be governance parameters modifiable with |
e33ca82
to
94c00a3
Compare
baseapp/baseapp.go
Outdated
if err != nil { | ||
result = err.Result() | ||
} | ||
result = app.runTx(true, true, 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.
I think we can do this through Query, but we can't just use runTx
as is because we want a fresh throw-away state to run the simulation against.
If we do it as is, it will update our checktx state, which sounds appealing, but might not be good because then when we try to add it to the tendermint mempool it will call check tx and possibly fail (since the tx was already executed against the checktx state in the app without tendermint knowing).
So we probably need to refactor runTx to take a ctx so we can pass in the ctx we want and create something fresh every time simulate
is called that just gets thrown away after.
Of course this also means that we cant run muiltiple dependent simulate
in a row without waiting for block commits.
An alternative option would be to open another connection between Tendermint and App and expose that over the Tendermitn RPC but that would be much more involved ...
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.
Presently, runTx
with the simulateDeliver
flag doesn't write to the multistore -94c00a3.
Ref #979, now also addressed (not p2p queries though) |
bad5413
to
48bad69
Compare
To-do:
|
552dfda
to
1086e35
Compare
Ready for first-pass review @rigelrozanski @ebuchman |
Also @sunnya97 all the gas costs should be governance-controlled parameters once governance is merged (glad to help). |
baseapp/baseapp.go
Outdated
@@ -27,6 +28,7 @@ type BaseApp struct { | |||
// initialized on creation | |||
Logger log.Logger | |||
name string // application name from abci.Info | |||
codec *wire.Codec // Amino codec |
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.
let's stick to cdc
? that's everywhere really
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.
Updated to cdc
.
Would be nice to add crypto wrapper operations with gas costs - however, a bit complex because the go-crypto |
79c248e
to
3505ce7
Compare
Now includes p2p query functions, ref #979 |
be054dc
to
0cc1c52
Compare
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 Chris. This looks great - most comments can be later TODOs, but I think it would be nice if we didn't add gasLimit to NewBaseApp
baseapp/baseapp.go
Outdated
msg := "application doesn't support queries" | ||
return sdk.ErrUnknownRequest(msg).QueryResult() | ||
path := req.Path | ||
// "/app" prefix for special application queries |
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 ran strings.Split
on /
and switched on it ? Would be nice not to slice strings with magic numbers everywhere
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.
Agreed, updated.
baseapp/baseapp.go
Outdated
} | ||
|
||
// txBytes may be nil in some cases, eg. in tests. | ||
// Also, in the future we may support "internal" transactions. | ||
func (app *BaseApp) runTx(isCheckTx bool, txBytes []byte, tx sdk.Tx) (result sdk.Result) { | ||
func (app *BaseApp) runTx(isCheckTx bool, simulateDeliver bool, txBytes []byte, tx sdk.Tx) (result sdk.Result) { |
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.
maybe runTx should take a runMode
, an enum for checkTx
, simulateDeliver
, etc. Though probably premature until we know an actual third kind of runTx we need to support - ?
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 already have three: check
, simulate
, deliver
. Updated to use an enum.
func (gi *gasKVStore) Get(key []byte) (value []byte) { | ||
gi.gasMeter.ConsumeGas(ReadCostFlat, "GetFlat") | ||
value = gi.parent.Get(key) | ||
// TODO overflow-safe math? |
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 open an issue for it
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.
Ref #869
x/bank/keeper.go
Outdated
@@ -108,6 +108,7 @@ func (keeper ViewKeeper) HasCoins(ctx sdk.Context, addr sdk.Address, amt sdk.Coi | |||
//______________________________________________________________________________________________ | |||
|
|||
func getCoins(ctx sdk.Context, am sdk.AccountMapper, addr sdk.Address) sdk.Coins { | |||
ctx.GasMeter().ConsumeGas(10, "getCoins") |
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.
let's get a list of constants for these ... possibly parameters one day ...
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.
Switched to constants at top of file. Also, these gas costs are probably wrong / may be unnecessary with the GasKVStore.
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.
baseapp/baseapp.go
Outdated
@@ -398,6 +485,14 @@ func (app *BaseApp) runTx(isCheckTx bool, txBytes []byte, tx sdk.Tx) (result sdk | |||
ctx = app.deliverState.ctx.WithTxBytes(txBytes) | |||
} | |||
|
|||
// Create a new zeroed gas meter | |||
ctx = ctx.WithGasMeter(sdk.NewGasMeter(app.txGasLimit)) |
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.
doesn't the gas meter need to use the gas provided in the tx, rather than this app level limit ? Perhaps we need to do this set up in the anteHandler
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.
Yes, this is wrong, thanks. Switched to ante handler.
Do we also need to check that tx.Fee.Gas <= app.txGasLimit
, or will Tendermint do that for us?
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'll need to #1007
baseapp/baseapp.go
Outdated
@@ -57,15 +62,17 @@ var _ abci.Application = (*BaseApp)(nil) | |||
|
|||
// Create and name new BaseApp | |||
// NOTE: The db is used to store the version number for now. | |||
func NewBaseApp(name string, cdc *wire.Codec, logger log.Logger, db dbm.DB) *BaseApp { | |||
func NewBaseApp(name string, cdc *wire.Codec, logger log.Logger, db dbm.DB, txGasLimit sdk.Gas) *BaseApp { |
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.
Seems strange that txGasLimit would become so first class as to be an arg to NewBaseApp - is there a good reason for this ?
Also, BaseApp should probably have a ConsensusParams that mirrors Tendermint's - MaxGasPerTx is part of that , gets initialized by InitChain, and can be updated by EndBlock. Then we shouldnt need to pass txGasLimit in everywhere.
In the meantime anyways I'd rather use setters and defaults than add function args
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.
Agreed on ConsensusParams
, made an issue: #1007
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.
Removed txGasLimit
, if Tendermint enforces that we may not need it at all actually.
Ref #1008 |
baseapp/baseapp.go
Outdated
if len(path) > 0 && path[0] == "" { | ||
path = path[1:] | ||
} | ||
fmt.Sprintf("Path: %v\n", path) |
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.
remove
baseapp/baseapp.go
Outdated
@@ -210,9 +233,9 @@ func (app *BaseApp) initFromStore(mainKey sdk.StoreKey) error { | |||
// NewContext returns a new Context with the correct store, the given header, and nil txBytes. | |||
func (app *BaseApp) NewContext(isCheckTx bool, header abci.Header) sdk.Context { | |||
if isCheckTx { | |||
return sdk.NewContext(app.checkState.ms, header, true, nil, app.Logger) | |||
return sdk.NewContext(app.checkState.ms, header, true, nil, app.Logger, 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.
can we remove passing the gaslimit here too ? Seems like we're not using it anymore (InfiniteGasMeter ?)
I can finish up and merge this, thanks! |
there is no version 4.6.2, 4.2.1 is the latest 4.x release
Ref #962
See questions on issue.