diff --git a/PENDING.md b/PENDING.md index 932b3554a7..3f5c8e9678 100644 --- a/PENDING.md +++ b/PENDING.md @@ -69,5 +69,6 @@ BUG FIXES * SDK * \#2967 Change ordering of `mint.BeginBlocker` and `distr.BeginBlocker`, recalculate inflation each block + * \#3071 Catch overflow on block gas meter * Tendermint diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index eeeea53da5..c3042b5883 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -701,6 +701,11 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk return } + var startingGas uint64 + if mode == runTxModeDeliver { + startingGas = ctx.BlockGasMeter().GasConsumed() + } + defer func() { if r := recover(); r != nil { switch rType := r.(type) { @@ -726,6 +731,9 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk if mode == runTxModeDeliver { ctx.BlockGasMeter().ConsumeGas( ctx.GasMeter().GasConsumedToLimit(), "block gas meter") + if ctx.BlockGasMeter().GasConsumed() < startingGas { + panic(sdk.ErrorGasOverflow{"tx gas summation"}) + } } }() diff --git a/types/errors.go b/types/errors.go index 46436531ef..9e4d880dfd 100644 --- a/types/errors.go +++ b/types/errors.go @@ -43,6 +43,7 @@ const ( CodeMemoTooLarge CodeType = 13 CodeInsufficientFee CodeType = 14 CodeTooManySignatures CodeType = 15 + CodeGasOverflow CodeType = 16 // CodespaceRoot is a codespace for error codes in this file only. // Notice that 0 is an "unset" codespace, which can be overridden with @@ -143,6 +144,9 @@ func ErrInsufficientFee(msg string) Error { func ErrTooManySignatures(msg string) Error { return newErrorWithRootCodespace(CodeTooManySignatures, msg) } +func ErrGasOverflow(msg string) Error { + return newErrorWithRootCodespace(CodeGasOverflow, msg) +} //---------------------------------------- // Error & sdkError diff --git a/x/auth/stdtx.go b/x/auth/stdtx.go index f648d7e77c..d1895a1944 100644 --- a/x/auth/stdtx.go +++ b/x/auth/stdtx.go @@ -43,7 +43,7 @@ func (tx StdTx) ValidateBasic() sdk.Error { stdSigs := tx.GetSignatures() if tx.Fee.Gas > maxGasWanted { - return sdk.ErrInternal(fmt.Sprintf("invalid gas supplied; %d > %d", tx.Fee.Gas, maxGasWanted)) + return sdk.ErrGasOverflow(fmt.Sprintf("invalid gas supplied; %d > %d", tx.Fee.Gas, maxGasWanted)) } if !tx.Fee.Amount.IsNotNegative() { return sdk.ErrInsufficientFee(fmt.Sprintf("invalid fee %s amount provided", tx.Fee.Amount)) diff --git a/x/auth/stdtx_test.go b/x/auth/stdtx_test.go index 7359444209..1ad9ef6e2a 100644 --- a/x/auth/stdtx_test.go +++ b/x/auth/stdtx_test.go @@ -127,7 +127,7 @@ func TestTxValidateBasic(t *testing.T) { err = tx.ValidateBasic() require.Error(t, err) - require.Equal(t, sdk.CodeInternal, err.Result().Code) + require.Equal(t, sdk.CodeGasOverflow, err.Result().Code) // require to pass when above criteria are matched privs, accNums, seqs = []crypto.PrivKey{priv1, priv2}, []uint64{0, 1}, []uint64{0, 0}