Ensure query isolation (#611)

* Ensure query isolation

* Review feedback
This commit is contained in:
Alexander Peters
2021-09-14 17:25:05 +02:00
committed by GitHub
parent 454576a2e8
commit a447ee0c12
2 changed files with 36 additions and 4 deletions

View File

@@ -1652,6 +1652,37 @@ func TestReply(t *testing.T) {
}
}
func TestQueryIsolation(t *testing.T) {
ctx, keepers := CreateTestInput(t, false, SupportedFeatures)
k := keepers.WasmKeeper
var mock wasmtesting.MockWasmer
wasmtesting.MakeInstantiable(&mock)
example := SeedNewContractInstance(t, ctx, keepers, &mock)
WithQueryHandlerDecorator(func(other WasmVMQueryHandler) WasmVMQueryHandler {
return WasmVMQueryHandlerFn(func(ctx sdk.Context, caller sdk.AccAddress, request wasmvmtypes.QueryRequest) ([]byte, error) {
if request.Custom == nil {
return other.HandleQuery(ctx, caller, request)
}
// here we write to DB which should not be persisted
ctx.KVStore(k.storeKey).Set([]byte(`set_in_query`), []byte(`this_is_allowed`))
return nil, nil
})
}).apply(k)
// when
mock.ReplyFn = func(codeID wasmvm.Checksum, env wasmvmtypes.Env, reply wasmvmtypes.Reply, store wasmvm.KVStore, goapi wasmvm.GoAPI, querier wasmvm.Querier, gasMeter wasmvm.GasMeter, gasLimit uint64, deserCost wasmvmtypes.UFraction) (*wasmvmtypes.Response, uint64, error) {
_, err := querier.Query(wasmvmtypes.QueryRequest{
Custom: []byte(`{}`),
}, 1_000_000)
require.NoError(t, err)
return &wasmvmtypes.Response{}, 0, nil
}
em := sdk.NewEventManager()
_, gotErr := k.reply(ctx.WithEventManager(em), example.Contract, wasmvmtypes.Reply{})
require.NoError(t, gotErr)
assert.Nil(t, ctx.KVStore(k.storeKey).Get([]byte(`set_in_query`)))
}
func TestBuildContractAddress(t *testing.T) {
specs := map[string]struct {
srcCodeID uint64

View File

@@ -46,15 +46,16 @@ type GRPCQueryRouter interface {
var _ wasmvmtypes.Querier = QueryHandler{}
func (q QueryHandler) Query(request wasmvmtypes.QueryRequest, gasLimit uint64) ([]byte, error) {
// set a limit for a subctx
// set a limit for a subCtx
sdkGas := q.gasRegister.FromWasmVMGas(gasLimit)
subctx := q.Ctx.WithGasMeter(sdk.NewGasMeter(sdkGas))
// discard all changes/ events in subCtx by not committing the cached context
subCtx, _ := q.Ctx.WithGasMeter(sdk.NewGasMeter(sdkGas)).CacheContext()
// make sure we charge the higher level context even on panic
defer func() {
q.Ctx.GasMeter().ConsumeGas(subctx.GasMeter().GasConsumed(), "contract sub-query")
q.Ctx.GasMeter().ConsumeGas(subCtx.GasMeter().GasConsumed(), "contract sub-query")
}()
return q.Plugins.HandleQuery(subctx, q.Caller, request)
return q.Plugins.HandleQuery(subCtx, q.Caller, request)
}
func (q QueryHandler) GasConsumed() uint64 {