Consume block gas to tx gas limit even upon overconsumption
This commit is contained in:
parent
10bdf8fa03
commit
4afd53d81b
|
@ -688,7 +688,7 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
|
|||
ctx = app.initializeContext(ctx, mode)
|
||||
|
||||
// only run the tx if there is block gas remaining
|
||||
if mode == runTxModeDeliver && ctx.BlockGasMeter().PastLimit() {
|
||||
if mode == runTxModeDeliver && ctx.BlockGasMeter().IsOutOfGas() {
|
||||
result = sdk.ErrOutOfGas("no block gas left to run tx").Result()
|
||||
return
|
||||
}
|
||||
|
@ -705,6 +705,12 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
|
|||
}
|
||||
}
|
||||
|
||||
// consume block gas whether panic or not.
|
||||
if mode == runTxModeDeliver {
|
||||
ctx.BlockGasMeter().ConsumeGas(
|
||||
ctx.GasMeter().GasConsumedToLimit(), "block gas meter")
|
||||
}
|
||||
|
||||
result.GasWanted = gasWanted
|
||||
result.GasUsed = ctx.GasMeter().GasConsumed()
|
||||
}()
|
||||
|
@ -750,12 +756,6 @@ func (app *BaseApp) runTx(mode runTxMode, txBytes []byte, tx sdk.Tx) (result sdk
|
|||
result = app.runMsgs(runMsgCtx, msgs, mode)
|
||||
result.GasWanted = gasWanted
|
||||
|
||||
// consume block gas
|
||||
if mode == runTxModeDeliver {
|
||||
ctx.BlockGasMeter().ConsumeGas(
|
||||
ctx.GasMeter().GasConsumed(), "block gas meter")
|
||||
}
|
||||
|
||||
// only update state if all messages pass
|
||||
if result.IsOK() {
|
||||
msCache.Write()
|
||||
|
|
|
@ -943,16 +943,16 @@ func TestMaxBlockGasLimits(t *testing.T) {
|
|||
if tc.fail && (j+1) > tc.failAfterDeliver {
|
||||
require.Equal(t, res.Code, sdk.CodeOutOfGas, fmt.Sprintf("%d: %v, %v", i, tc, res))
|
||||
require.Equal(t, res.Codespace, sdk.CodespaceRoot, fmt.Sprintf("%d: %v, %v", i, tc, res))
|
||||
require.True(t, ctx.BlockGasMeter().PastLimit())
|
||||
//require.True(t, ctx.BlockGasMeter().IsPastLimit()) NOTE: not necessarily true.
|
||||
require.True(t, ctx.BlockGasMeter().IsOutOfGas())
|
||||
} else {
|
||||
|
||||
// check gas used and wanted
|
||||
expBlockGasUsed := tc.gasUsedPerDeliver * uint64(j+1)
|
||||
require.Equal(t, expBlockGasUsed, blockGasUsed,
|
||||
fmt.Sprintf("%d,%d: %v, %v, %v, %v", i, j, tc, expBlockGasUsed, blockGasUsed, res))
|
||||
|
||||
require.True(t, res.IsOK(), fmt.Sprintf("%d,%d: %v, %v", i, j, tc, res))
|
||||
require.False(t, ctx.BlockGasMeter().PastLimit())
|
||||
require.False(t, ctx.BlockGasMeter().IsPastLimit())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
37
types/gas.go
37
types/gas.go
|
@ -34,8 +34,11 @@ type ErrorGasOverflow struct {
|
|||
// GasMeter interface to track gas consumption
|
||||
type GasMeter interface {
|
||||
GasConsumed() Gas
|
||||
GasConsumedToLimit() Gas
|
||||
Limit() Gas
|
||||
ConsumeGas(amount Gas, descriptor string)
|
||||
PastLimit() bool
|
||||
IsPastLimit() bool
|
||||
IsOutOfGas() bool
|
||||
}
|
||||
|
||||
type basicGasMeter struct {
|
||||
|
@ -55,6 +58,18 @@ func (g *basicGasMeter) GasConsumed() Gas {
|
|||
return g.consumed
|
||||
}
|
||||
|
||||
func (g *basicGasMeter) Limit() Gas {
|
||||
return g.limit
|
||||
}
|
||||
|
||||
func (g *basicGasMeter) GasConsumedToLimit() Gas {
|
||||
if g.consumed > g.limit {
|
||||
return g.limit
|
||||
} else {
|
||||
return g.consumed
|
||||
}
|
||||
}
|
||||
|
||||
func (g *basicGasMeter) ConsumeGas(amount Gas, descriptor string) {
|
||||
var overflow bool
|
||||
|
||||
|
@ -69,10 +84,14 @@ func (g *basicGasMeter) ConsumeGas(amount Gas, descriptor string) {
|
|||
}
|
||||
}
|
||||
|
||||
func (g *basicGasMeter) PastLimit() bool {
|
||||
func (g *basicGasMeter) IsPastLimit() bool {
|
||||
return g.consumed > g.limit
|
||||
}
|
||||
|
||||
func (g *basicGasMeter) IsOutOfGas() bool {
|
||||
return g.consumed >= g.limit
|
||||
}
|
||||
|
||||
type infiniteGasMeter struct {
|
||||
consumed Gas
|
||||
}
|
||||
|
@ -88,6 +107,14 @@ func (g *infiniteGasMeter) GasConsumed() Gas {
|
|||
return g.consumed
|
||||
}
|
||||
|
||||
func (g *infiniteGasMeter) GasConsumedToLimit() Gas {
|
||||
return g.consumed
|
||||
}
|
||||
|
||||
func (g *infiniteGasMeter) Limit() Gas {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (g *infiniteGasMeter) ConsumeGas(amount Gas, descriptor string) {
|
||||
var overflow bool
|
||||
|
||||
|
@ -98,7 +125,11 @@ func (g *infiniteGasMeter) ConsumeGas(amount Gas, descriptor string) {
|
|||
}
|
||||
}
|
||||
|
||||
func (g *infiniteGasMeter) PastLimit() bool {
|
||||
func (g *infiniteGasMeter) IsPastLimit() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *infiniteGasMeter) IsOutOfGas() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
@ -27,9 +27,18 @@ func TestGasMeter(t *testing.T) {
|
|||
used += usage
|
||||
require.NotPanics(t, func() { meter.ConsumeGas(usage, "") }, "Not exceeded limit but panicked. tc #%d, usage #%d", tcnum, unum)
|
||||
require.Equal(t, used, meter.GasConsumed(), "Gas consumption not match. tc #%d, usage #%d", tcnum, unum)
|
||||
require.Equal(t, used, meter.GasConsumedToLimit(), "Gas consumption (to limit) not match. tc #%d, usage #%d", tcnum, unum)
|
||||
require.False(t, meter.IsPastLimit(), "Not exceeded limit but got IsPastLimit() true")
|
||||
if unum < len(tc.usage)-1 {
|
||||
require.False(t, meter.IsOutOfGas(), "Not yet at limit but got IsOutOfGas() true")
|
||||
} else {
|
||||
require.True(t, meter.IsOutOfGas(), "At limit but got IsOutOfGas() false")
|
||||
}
|
||||
}
|
||||
|
||||
require.Panics(t, func() { meter.ConsumeGas(1, "") }, "Exceeded but not panicked. tc #%d", tcnum)
|
||||
require.Equal(t, meter.GasConsumedToLimit(), meter.Limit(), "Gas consumption (to limit) not match limit")
|
||||
require.Equal(t, meter.GasConsumed(), meter.Limit()+1, "Gas consumption not match limit+1")
|
||||
break
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue