diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a0c1a972..641b211b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## [v0.5.9] + +### Bug Fixes +- [\#588](https://github.com/terra-money/core/pull/588) - fix wasm external querier to use single wasmvm with context value + ## [v0.5.8] ### Bug Fixes diff --git a/x/wasm/keeper/contract.go b/x/wasm/keeper/contract.go index c5f9b5a2a..a02ae3973 100644 --- a/x/wasm/keeper/contract.go +++ b/x/wasm/keeper/contract.go @@ -420,7 +420,7 @@ func (k Keeper) queryToStore(ctx sdk.Context, contractAddress sdk.AccAddress, ke return prefixStore.Get(key) } -func (k Keeper) queryToContract(ctx sdk.Context, contractAddress sdk.AccAddress, queryMsg []byte, wasmVMs ...types.WasmerEngine) ([]byte, error) { +func (k Keeper) queryToContract(ctx sdk.Context, contractAddress sdk.AccAddress, queryMsg []byte) ([]byte, error) { defer telemetry.MeasureSince(time.Now(), "wasm", "contract", "query-smart") ctx.GasMeter().ConsumeGas(types.InstantiateContractCosts(len(queryMsg)), "Loading CosmWasm module: query") @@ -432,9 +432,11 @@ func (k Keeper) queryToContract(ctx sdk.Context, contractAddress sdk.AccAddress, env := types.NewEnv(ctx, contractAddress) // when the vm is given, use that given vm - wasmVM := k.wasmVM - if len(wasmVMs) != 0 { - wasmVM = wasmVMs[0] + var wasmVM types.WasmerEngine + if vm := ctx.Context().Value(types.QueryWasmVMContextKey); vm != nil { + wasmVM = vm.(types.WasmerEngine) + } else { + wasmVM = k.wasmVM } // assert max depth to prevent stack overflow diff --git a/x/wasm/keeper/keeper.go b/x/wasm/keeper/keeper.go index f71439dfa..d0d404d1d 100644 --- a/x/wasm/keeper/keeper.go +++ b/x/wasm/keeper/keeper.go @@ -35,7 +35,7 @@ type Keeper struct { queryRouter types.GRPCQueryRouter wasmVM types.WasmerEngine - wasmReadVMPool []types.WasmerEngine + wasmReadVMPool *[]types.WasmerEngine wasmReadVMSemaphore *semaphore.Weighted wasmReadVMMutex *sync.Mutex @@ -114,7 +114,7 @@ func NewKeeper( cdc: cdc, paramSpace: paramspace, wasmVM: writeWasmVM, - wasmReadVMPool: wasmReadVMPool, + wasmReadVMPool: &wasmReadVMPool, wasmReadVMSemaphore: semaphore.NewWeighted(int64(numReadVms)), wasmReadVMMutex: &sync.Mutex{}, accountKeeper: accountKeeper, diff --git a/x/wasm/keeper/legacy_querier.go b/x/wasm/keeper/legacy_querier.go index 7c8fa8035..405bab09d 100644 --- a/x/wasm/keeper/legacy_querier.go +++ b/x/wasm/keeper/legacy_querier.go @@ -1,6 +1,7 @@ package keeper import ( + "context" "fmt" "runtime/debug" @@ -147,7 +148,9 @@ func queryContractStore(ctx sdk.Context, req abci.RequestQuery, k Keeper, legacy } }() - bz, err = k.queryToContract(ctx, params.ContractAddress, params.Msg, wasmVM) + // store query wasmvm in the context + ctx = ctx.WithContext(context.WithValue(ctx.Context(), types.QueryWasmVMContextKey, wasmVM)) + bz, err = k.queryToContract(ctx, params.ContractAddress, params.Msg) return } diff --git a/x/wasm/keeper/pool.go b/x/wasm/keeper/pool.go index 63a70e8b0..0d7bf5610 100644 --- a/x/wasm/keeper/pool.go +++ b/x/wasm/keeper/pool.go @@ -6,8 +6,6 @@ import ( "github.com/terra-money/core/x/wasm/types" ) -var n = 0 - func (k Keeper) acquireWasmVM(ctx context.Context) (types.WasmerEngine, error) { err := k.wasmReadVMSemaphore.Acquire(ctx, 1) if err != nil { @@ -15,8 +13,8 @@ func (k Keeper) acquireWasmVM(ctx context.Context) (types.WasmerEngine, error) { } k.wasmReadVMMutex.Lock() - wasmVM := k.wasmReadVMPool[0] - k.wasmReadVMPool = k.wasmReadVMPool[1:] + wasmVM := (*k.wasmReadVMPool)[0] + *k.wasmReadVMPool = (*k.wasmReadVMPool)[1:] k.wasmReadVMMutex.Unlock() return wasmVM, nil @@ -24,7 +22,7 @@ func (k Keeper) acquireWasmVM(ctx context.Context) (types.WasmerEngine, error) { func (k Keeper) releaseWasmVM(wasmVM types.WasmerEngine) { k.wasmReadVMMutex.Lock() - k.wasmReadVMPool = append(k.wasmReadVMPool, wasmVM) + *k.wasmReadVMPool = append(*k.wasmReadVMPool, wasmVM) k.wasmReadVMMutex.Unlock() k.wasmReadVMSemaphore.Release(1) diff --git a/x/wasm/keeper/querier.go b/x/wasm/keeper/querier.go index e15261be1..6f03bc6f0 100644 --- a/x/wasm/keeper/querier.go +++ b/x/wasm/keeper/querier.go @@ -120,8 +120,9 @@ func (q querier) ContractStore(c context.Context, req *types.QueryContractStoreR } }() - var bz []byte - bz, err = q.queryToContract(ctx, contractAddr, req.QueryMsg, wasmVM) + // store query wasmvm in the context + ctx = ctx.WithContext(context.WithValue(ctx.Context(), types.QueryWasmVMContextKey, wasmVM)) + bz, err := q.queryToContract(ctx, contractAddr, req.QueryMsg) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/x/wasm/keeper/recursive_test.go b/x/wasm/keeper/recursive_test.go index b6989300e..88eb5fb11 100644 --- a/x/wasm/keeper/recursive_test.go +++ b/x/wasm/keeper/recursive_test.go @@ -1,6 +1,7 @@ package keeper import ( + "context" "encoding/json" "io/ioutil" "testing" @@ -344,18 +345,25 @@ func TestLimitRecursiveQueryGas(t *testing.T) { } func TestLimitRecursiveQueryDepth(t *testing.T) { - contractAddr, _, ctx, keeper, _ := initRecurseContract(t) + // pick query wasmvm + wasmvm, err := keeper.acquireWasmVM(ctx.Context()) + require.NoError(t, err) + defer keeper.releaseWasmVM(wasmvm) + + ctx = ctx.WithContext(context.WithValue(ctx.Context(), types.QueryWasmVMContextKey, wasmvm)) + + // exceed max query depth msg := buildQuery(t, Recurse{ - Depth: types.ContractMaxQueryDepth - 1, // need to include first query + Depth: types.ContractMaxQueryDepth, }) - _, err := keeper.queryToContract(ctx, contractAddr, msg) - require.NoError(t, err) + _, err = keeper.queryToContract(ctx, contractAddr, msg) + require.Error(t, err) msg = buildQuery(t, Recurse{ - Depth: types.ContractMaxQueryDepth, + Depth: types.ContractMaxQueryDepth - 1, // need to include first query }) _, err = keeper.queryToContract(ctx, contractAddr, msg) - require.Error(t, err) + require.NoError(t, err) } diff --git a/x/wasm/types/keys.go b/x/wasm/types/keys.go index 064291b57..9371fe0bb 100644 --- a/x/wasm/types/keys.go +++ b/x/wasm/types/keys.go @@ -20,6 +20,9 @@ const ( // RouterKey is the msg router key for the wasm module RouterKey = ModuleName + + // QueryWasmVMContextKey is the context key to store wasmvm in query context + QueryWasmVMContextKey = "wasmvm" ) // Keys for wasm store