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

Unexpectedly high gas usage in delegate transaction on game_of_stakes_3 #3242

Closed
4 tasks
zmanian opened this issue Jan 7, 2019 · 6 comments · Fixed by #3244
Closed
4 tasks

Unexpectedly high gas usage in delegate transaction on game_of_stakes_3 #3242

zmanian opened this issue Jan 7, 2019 · 6 comments · Fixed by #3244
Assignees

Comments

@zmanian
Copy link
Member

zmanian commented Jan 7, 2019

We have seen a number of delegate transactions in Game of Stakes fail due to unexpected gas usage.

https://hubble.figment.network/chains/gos3/blocks/19486

Contains an example.

No pattern has been identified except that only delegate transactions appear to demonstrate unexpectedly high gas usage.

This is has also only been observed when adding coins to existing delegation and not when creating a new delegation.


For Admin Use

  • Not duplicate issue
  • Appropriate labels applied
  • Appropriate contributors tagged
  • Contributor assigned/self-assigned
@eon0001
Copy link

eon0001 commented Jan 7, 2019

I experienced the same issue even in case of withdraw rewards transaction.

https://stargazer.certus.one/blocks/31071

@alexanderbez
Copy link
Contributor

alexanderbez commented Jan 7, 2019

Something related to hooks most likely.

/cc @cwgoes @rigelrozanski

@alexanderbez alexanderbez added T:Bug C:x/staking C:x/distribution distribution module related labels Jan 7, 2019
@hendrikhofstadt
Copy link
Contributor

hendrikhofstadt commented Jan 7, 2019

@alexanderbez It is actually not.

What happens is that the first transaction in the block has an invalid signature which causes the tx processing to abort.

if abort {
return result
}
if !newCtx.IsZero() {
// At this point, newCtx.MultiStore() is cache wrapped,
// or something else replaced by anteHandler.
// We want the original ms, not one which was cache-wrapped
// for the ante handler.
ctx = newCtx.WithMultiStore(ms)
}

However that also means that the context is not overwritten.
The problem is that the newCtx contains the actual gas meter of the transaction.
So now the deferred function is called:

defer func() {
if mode == runTxModeDeliver {
ctx.BlockGasMeter().ConsumeGas(
ctx.GasMeter().GasConsumedToLimit(), "block gas meter")
if ctx.BlockGasMeter().GasConsumed() < startingGas {
panic(sdk.ErrorGasOverflow{"tx gas summation"})
}
}
}()

That function consumes the gas from the ctx's gas meter. However since the ctx has not been overwritten this is still the infinite gas meter from BeginBlocker.

Subsequently the whole gas from BeginBlocker is then consumed in the first TX which is too much for the block as normally that gas should have never been consumed.

@alexanderbez
Copy link
Contributor

alexanderbez commented Jan 7, 2019

Hmmm so the infiniteGasMeter will simply return/consume the total consumed which is past the limit.

Is something along the following occurring for a given block:

  1. Sig verification fails on 1st tx, gas meter is still infinite and already has some consumed gas.
  2. Subsequent txs pass sig verification thus getting a non-infinite gas meter and eventually exceeding the limit.

@hendrikhofstadt
Copy link
Contributor

hendrikhofstadt commented Jan 7, 2019

@alexanderbez I don't have a PR open. Feel free to open one.

It should be as simple as not consuming gas if the tx is aborted (if that's the intended behaviour)

Edit: Thinking about possible DoS vectors it would make sense to just consume the gas from the newCtx that has been consumed until the execution was aborted.

@alexanderbez
Copy link
Contributor

alexanderbez commented Jan 7, 2019

A bit confused actually, as I cannot see how during deliverTx, an infinite gas meter would ever be used (assuming there is a consensusParams.BlockSize set)?

Edit: As @SLAMPER pointed out, ctx.GasMeter().GasConsumedToLimit(), "block gas meter") is the culprit here where the meter is an infinite one when aborted.

@alexanderbez alexanderbez added C:baseapp and removed C:x/distribution distribution module related C:x/staking labels Jan 7, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants