diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index d3bf85fe8..36843b776 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -35,6 +35,7 @@ type BaseApp struct { // must be set txDecoder sdk.TxDecoder // unmarshal []byte into sdk.Tx anteHandler sdk.AnteHandler // ante handler for fee and auth + txGasLimit sdk.Gas // per-transaction gas limit // may be nil initChainer sdk.InitChainer // initialize state with validators and state blob @@ -66,6 +67,7 @@ func NewBaseApp(name string, cdc *wire.Codec, logger log.Logger, db dbm.DB) *Bas router: NewRouter(), codespacer: sdk.NewCodespacer(), txDecoder: defaultTxDecoder(cdc), + txGasLimit: sdk.Gas(10000), } // Register the undefined & root codespaces, which should not be used by any modules app.codespacer.RegisterOrPanic(sdk.CodespaceUndefined) @@ -210,9 +212,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, app.txGasLimit) } - return sdk.NewContext(app.deliverState.ms, header, false, nil, app.Logger) + return sdk.NewContext(app.deliverState.ms, header, false, nil, app.Logger, app.txGasLimit) } type state struct { @@ -228,7 +230,7 @@ func (app *BaseApp) setCheckState(header abci.Header) { ms := app.cms.CacheMultiStore() app.checkState = &state{ ms: ms, - ctx: sdk.NewContext(ms, header, true, nil, app.Logger), + ctx: sdk.NewContext(ms, header, true, nil, app.Logger, app.txGasLimit), } } @@ -236,7 +238,7 @@ func (app *BaseApp) setDeliverState(header abci.Header) { ms := app.cms.CacheMultiStore() app.deliverState = &state{ ms: ms, - ctx: sdk.NewContext(ms, header, false, nil, app.Logger), + ctx: sdk.NewContext(ms, header, false, nil, app.Logger, app.txGasLimit), } } diff --git a/examples/democoin/x/cool/keeper_test.go b/examples/democoin/x/cool/keeper_test.go index d497dee69..10e958ce7 100644 --- a/examples/democoin/x/cool/keeper_test.go +++ b/examples/democoin/x/cool/keeper_test.go @@ -30,7 +30,7 @@ func TestCoolKeeper(t *testing.T) { auth.RegisterBaseAccount(cdc) am := auth.NewAccountMapper(cdc, capKey, &auth.BaseAccount{}) - ctx := sdk.NewContext(ms, abci.Header{}, false, nil, nil) + ctx := sdk.NewContext(ms, abci.Header{}, false, nil, nil, 0) ck := bank.NewKeeper(am) keeper := NewKeeper(capKey, ck, DefaultCodespace) diff --git a/examples/democoin/x/pow/handler_test.go b/examples/democoin/x/pow/handler_test.go index 30aeafa2a..48e9c53e7 100644 --- a/examples/democoin/x/pow/handler_test.go +++ b/examples/democoin/x/pow/handler_test.go @@ -20,7 +20,7 @@ func TestPowHandler(t *testing.T) { auth.RegisterBaseAccount(cdc) am := auth.NewAccountMapper(cdc, capKey, &auth.BaseAccount{}) - ctx := sdk.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger()) + ctx := sdk.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger(), 0) config := NewConfig("pow", int64(1)) ck := bank.NewKeeper(am) keeper := NewKeeper(capKey, config, ck, DefaultCodespace) diff --git a/examples/democoin/x/pow/keeper_test.go b/examples/democoin/x/pow/keeper_test.go index a4afb876a..324cdcdce 100644 --- a/examples/democoin/x/pow/keeper_test.go +++ b/examples/democoin/x/pow/keeper_test.go @@ -33,7 +33,7 @@ func TestPowKeeperGetSet(t *testing.T) { auth.RegisterBaseAccount(cdc) am := auth.NewAccountMapper(cdc, capKey, &auth.BaseAccount{}) - ctx := sdk.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger()) + ctx := sdk.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger(), 0) config := NewConfig("pow", int64(1)) ck := bank.NewKeeper(am) keeper := NewKeeper(capKey, config, ck, DefaultCodespace) diff --git a/examples/democoin/x/simplestake/keeper_test.go b/examples/democoin/x/simplestake/keeper_test.go index 302a2e58b..1d19a61d7 100644 --- a/examples/democoin/x/simplestake/keeper_test.go +++ b/examples/democoin/x/simplestake/keeper_test.go @@ -33,7 +33,7 @@ func setupMultiStore() (sdk.MultiStore, *sdk.KVStoreKey, *sdk.KVStoreKey) { func TestKeeperGetSet(t *testing.T) { ms, _, capKey := setupMultiStore() - ctx := sdk.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger()) + ctx := sdk.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger(), 0) stakeKeeper := NewKeeper(capKey, bank.NewKeeper(nil), DefaultCodespace) addr := sdk.Address([]byte("some-address")) @@ -60,7 +60,7 @@ func TestBonding(t *testing.T) { cdc := wire.NewCodec() auth.RegisterBaseAccount(cdc) - ctx := sdk.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger()) + ctx := sdk.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger(), 0) accountMapper := auth.NewAccountMapper(cdc, authKey, &auth.BaseAccount{}) coinKeeper := bank.NewKeeper(accountMapper) diff --git a/types/context.go b/types/context.go index b3f30a2e0..33713d353 100644 --- a/types/context.go +++ b/types/context.go @@ -30,7 +30,7 @@ type Context struct { } // create a new context -func NewContext(ms MultiStore, header abci.Header, isCheckTx bool, txBytes []byte, logger log.Logger) Context { +func NewContext(ms MultiStore, header abci.Header, isCheckTx bool, txBytes []byte, logger log.Logger, gasLimit Gas) Context { c := Context{ Context: context.Background(), pst: newThePast(), @@ -43,8 +43,7 @@ func NewContext(ms MultiStore, header abci.Header, isCheckTx bool, txBytes []byt c = c.WithIsCheckTx(isCheckTx) c = c.WithTxBytes(txBytes) c = c.WithLogger(logger) - c = c.WithGasLimit(0) - c = c.WithGasConsumed(0) + c = c.WithGasMeter(NewGasMeter(gasLimit)) return c } @@ -129,8 +128,7 @@ const ( contextKeyIsCheckTx contextKeyTxBytes contextKeyLogger - contextKeyGasLimit - contextKeyGasConsumed + contextKeyGasMeter ) // NOTE: Do not expose MultiStore. @@ -159,11 +157,8 @@ func (c Context) TxBytes() []byte { func (c Context) Logger() log.Logger { return c.Value(contextKeyLogger).(log.Logger) } -func (c Context) GasLimit() uint64 { - return c.Value(contextKeyGasLimit).(uint64) -} -func (c Context) GasConsumed() uint64 { - return c.Value(contextKeyGasConsumed).(uint64) +func (c Context) GasMeter() GasMeter { + return c.Value(contextKeyGasMeter).(GasMeter) } func (c Context) WithMultiStore(ms MultiStore) Context { return c.withValue(contextKeyMultiStore, ms) @@ -187,11 +182,8 @@ func (c Context) WithTxBytes(txBytes []byte) Context { func (c Context) WithLogger(logger log.Logger) Context { return c.withValue(contextKeyLogger, logger) } -func (c Context) WithGasLimit(limit uint64) Context { - return c.withValue(contextKeyGasLimit, limit) -} -func (c Context) WithGasConsumed(consumed uint64) Context { - return c.withValue(contextKeyGasConsumed, consumed) +func (c Context) WithGasMeter(meter GasMeter) Context { + return c.withValue(contextKeyGasMeter, meter) } // Cache the multistore and return a new cached context. The cached context is diff --git a/types/context_test.go b/types/context_test.go index ec5faab44..9eafed625 100644 --- a/types/context_test.go +++ b/types/context_test.go @@ -43,7 +43,7 @@ func (l MockLogger) With(kvs ...interface{}) log.Logger { func TestContextGetOpShouldNeverPanic(t *testing.T) { var ms types.MultiStore - ctx := types.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger()) + ctx := types.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger(), 0) indices := []int64{ -10, 1, 0, 10, 20, } @@ -58,7 +58,7 @@ func defaultContext(key types.StoreKey) types.Context { cms := store.NewCommitMultiStore(db) cms.MountStoreWithDB(key, types.StoreTypeIAVL, db) cms.LoadLatestVersion() - ctx := types.NewContext(cms, abci.Header{}, false, nil, log.NewNopLogger()) + ctx := types.NewContext(cms, abci.Header{}, false, nil, log.NewNopLogger(), 0) return ctx } diff --git a/types/gas.go b/types/gas.go new file mode 100644 index 000000000..63aa71c1b --- /dev/null +++ b/types/gas.go @@ -0,0 +1,36 @@ +package types + +import () + +type Gas uint64 + +type GasMeter interface { + GasExceeded() bool + ConsumeGas(amount Gas) + ConsumeGasOrFail(amount Gas) bool +} + +type basicGasMeter struct { + limit Gas + consumed Gas +} + +func NewGasMeter(limit Gas) GasMeter { + return &basicGasMeter{ + limit: limit, + consumed: 0, + } +} + +func (g *basicGasMeter) GasExceeded() bool { + return g.consumed > g.limit +} + +func (g *basicGasMeter) ConsumeGas(amount Gas) { + g.consumed += amount +} + +func (g *basicGasMeter) ConsumeGasOrFail(amount Gas) bool { + g.ConsumeGas(amount) + return g.GasExceeded() +} diff --git a/types/lib/mapper_test.go b/types/lib/mapper_test.go index e1759b06a..ab6fb605a 100644 --- a/types/lib/mapper_test.go +++ b/types/lib/mapper_test.go @@ -25,7 +25,7 @@ func defaultComponents(key sdk.StoreKey) (sdk.Context, *wire.Codec) { cms := store.NewCommitMultiStore(db) cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) cms.LoadLatestVersion() - ctx := sdk.NewContext(cms, abci.Header{}, false, nil, log.NewNopLogger()) + ctx := sdk.NewContext(cms, abci.Header{}, false, nil, log.NewNopLogger(), 0) cdc := wire.NewCodec() return ctx, cdc } diff --git a/x/auth/ante_test.go b/x/auth/ante_test.go index ec296b12b..8310d3069 100644 --- a/x/auth/ante_test.go +++ b/x/auth/ante_test.go @@ -74,7 +74,7 @@ func TestAnteHandlerSigErrors(t *testing.T) { RegisterBaseAccount(cdc) mapper := NewAccountMapper(cdc, capKey, &BaseAccount{}) anteHandler := NewAnteHandler(mapper, BurnFeeHandler) - ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil, log.NewNopLogger()) + ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil, log.NewNopLogger(), 0) // keys and addresses priv1, addr1 := privAndAddr() @@ -115,7 +115,7 @@ func TestAnteHandlerSequences(t *testing.T) { RegisterBaseAccount(cdc) mapper := NewAccountMapper(cdc, capKey, &BaseAccount{}) anteHandler := NewAnteHandler(mapper, BurnFeeHandler) - ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil, log.NewNopLogger()) + ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil, log.NewNopLogger(), 0) // keys and addresses priv1, addr1 := privAndAddr() @@ -181,7 +181,7 @@ func TestAnteHandlerFees(t *testing.T) { RegisterBaseAccount(cdc) mapper := NewAccountMapper(cdc, capKey, &BaseAccount{}) anteHandler := NewAnteHandler(mapper, BurnFeeHandler) - ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil, log.NewNopLogger()) + ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil, log.NewNopLogger(), 0) // keys and addresses priv1, addr1 := privAndAddr() @@ -218,7 +218,7 @@ func TestAnteHandlerBadSignBytes(t *testing.T) { RegisterBaseAccount(cdc) mapper := NewAccountMapper(cdc, capKey, &BaseAccount{}) anteHandler := NewAnteHandler(mapper, BurnFeeHandler) - ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil, log.NewNopLogger()) + ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil, log.NewNopLogger(), 0) // keys and addresses priv1, addr1 := privAndAddr() @@ -293,7 +293,7 @@ func TestAnteHandlerSetPubKey(t *testing.T) { RegisterBaseAccount(cdc) mapper := NewAccountMapper(cdc, capKey, &BaseAccount{}) anteHandler := NewAnteHandler(mapper, BurnFeeHandler) - ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil, log.NewNopLogger()) + ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil, log.NewNopLogger(), 0) // keys and addresses priv1, addr1 := privAndAddr() diff --git a/x/auth/context_test.go b/x/auth/context_test.go index 89e318e0a..996a06889 100644 --- a/x/auth/context_test.go +++ b/x/auth/context_test.go @@ -13,7 +13,7 @@ import ( func TestContextWithSigners(t *testing.T) { ms, _ := setupMultiStore() - ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil, log.NewNopLogger()) + ctx := sdk.NewContext(ms, abci.Header{ChainID: "mychainid"}, false, nil, log.NewNopLogger(), 0) _, _, addr1 := keyPubAddr() _, _, addr2 := keyPubAddr() diff --git a/x/auth/mapper_test.go b/x/auth/mapper_test.go index cdd418990..80f673f99 100644 --- a/x/auth/mapper_test.go +++ b/x/auth/mapper_test.go @@ -29,7 +29,7 @@ func TestAccountMapperGetSet(t *testing.T) { RegisterBaseAccount(cdc) // make context and mapper - ctx := sdk.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger()) + ctx := sdk.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger(), 0) mapper := NewAccountMapper(cdc, capKey, &BaseAccount{}) addr := sdk.Address([]byte("some-address")) diff --git a/x/bank/keeper_test.go b/x/bank/keeper_test.go index 3db16c5f9..324152df2 100644 --- a/x/bank/keeper_test.go +++ b/x/bank/keeper_test.go @@ -31,7 +31,7 @@ func TestKeeper(t *testing.T) { cdc := wire.NewCodec() auth.RegisterBaseAccount(cdc) - ctx := sdk.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger()) + ctx := sdk.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger(), 0) accountMapper := auth.NewAccountMapper(cdc, authKey, &auth.BaseAccount{}) coinKeeper := NewKeeper(accountMapper) @@ -117,7 +117,7 @@ func TestSendKeeper(t *testing.T) { cdc := wire.NewCodec() auth.RegisterBaseAccount(cdc) - ctx := sdk.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger()) + ctx := sdk.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger(), 0) accountMapper := auth.NewAccountMapper(cdc, authKey, &auth.BaseAccount{}) coinKeeper := NewKeeper(accountMapper) sendKeeper := NewSendKeeper(accountMapper) @@ -186,7 +186,7 @@ func TestViewKeeper(t *testing.T) { cdc := wire.NewCodec() auth.RegisterBaseAccount(cdc) - ctx := sdk.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger()) + ctx := sdk.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger(), 0) accountMapper := auth.NewAccountMapper(cdc, authKey, &auth.BaseAccount{}) coinKeeper := NewKeeper(accountMapper) viewKeeper := NewViewKeeper(accountMapper) diff --git a/x/ibc/ibc_test.go b/x/ibc/ibc_test.go index 60cc59bad..298b5b462 100644 --- a/x/ibc/ibc_test.go +++ b/x/ibc/ibc_test.go @@ -24,7 +24,7 @@ func defaultContext(key sdk.StoreKey) sdk.Context { cms := store.NewCommitMultiStore(db) cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) cms.LoadLatestVersion() - ctx := sdk.NewContext(cms, abci.Header{}, false, nil, log.NewNopLogger()) + ctx := sdk.NewContext(cms, abci.Header{}, false, nil, log.NewNopLogger(), 0) return ctx } diff --git a/x/stake/test_common.go b/x/stake/test_common.go index 27acebe08..15c300d41 100644 --- a/x/stake/test_common.go +++ b/x/stake/test_common.go @@ -158,7 +158,7 @@ func createTestInput(t *testing.T, isCheckTx bool, initCoins int64) (sdk.Context err := ms.LoadLatestVersion() require.Nil(t, err) - ctx := sdk.NewContext(ms, abci.Header{ChainID: "foochainid"}, isCheckTx, nil, log.NewNopLogger()) + ctx := sdk.NewContext(ms, abci.Header{ChainID: "foochainid"}, isCheckTx, nil, log.NewNopLogger(), 0) cdc := makeTestCodec() accountMapper := auth.NewAccountMapper( cdc, // amino codec