Skip to content

Commit 9c00e87

Browse files
alpemattverse
authored andcommitted
Introduce AcceptListStargateQuerier (CosmWasm#1069)
* Stargate query enable * Remove initialized whitelists * Roman's review * Minor improvement * Add tests * Add testings and codec * Fix lint * Fix test * Fix from code review * Refactor Stargate querier init * Fix typo Co-authored-by: mattverse <[email protected]>
1 parent 881c77f commit 9c00e87

File tree

4 files changed

+283
-20
lines changed

4 files changed

+283
-20
lines changed

x/wasm/keeper/options.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func WithQueryHandlerDecorator(d func(old WasmVMQueryHandler) WasmVMQueryHandler
5858
}
5959

6060
// WithQueryPlugins is an optional constructor parameter to pass custom query plugins for wasmVM requests.
61-
// This option expects the default `QueryHandler` set an should not be combined with Option `WithQueryHandler` or `WithQueryHandlerDecorator`.
61+
// This option expects the default `QueryHandler` set and should not be combined with Option `WithQueryHandler` or `WithQueryHandlerDecorator`.
6262
func WithQueryPlugins(x *QueryPlugins) Option {
6363
return optsFn(func(k *Keeper) {
6464
q, ok := k.wasmVMQueryHandler.(QueryPlugins)

x/wasm/keeper/query_plugins.go

+62-4
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ package keeper
33
import (
44
"encoding/json"
55
"errors"
6+
"fmt"
67

78
abci "github.com/tendermint/tendermint/abci/types"
89

910
baseapp "github.com/Finschia/finschia-sdk/baseapp"
11+
"github.com/Finschia/finschia-sdk/codec"
1012
sdk "github.com/Finschia/finschia-sdk/types"
1113
sdkerrors "github.com/Finschia/finschia-sdk/types/errors"
1214
distributiontypes "github.com/Finschia/finschia-sdk/x/distribution/types"
@@ -107,7 +109,7 @@ func DefaultQueryPlugins(
107109
Custom: CustomQuerierImpl(queryRouter),
108110
IBC: IBCQuerier(wasm, channelKeeper),
109111
Staking: StakingQuerier(staking, distKeeper),
110-
Stargate: StargateQuerier(queryRouter),
112+
Stargate: RejectStargateQuerier(),
111113
Wasm: WasmQuerier(wasm),
112114
}
113115
}
@@ -302,9 +304,47 @@ func IBCQuerier(wasm contractMetaDataSource, channelKeeper types.ChannelKeeper)
302304
}
303305
}
304306

305-
func StargateQuerier(queryRouter GRPCQueryRouter) func(ctx sdk.Context, request *wasmvmtypes.StargateQuery) ([]byte, error) {
306-
return func(ctx sdk.Context, msg *wasmvmtypes.StargateQuery) ([]byte, error) {
307-
return nil, wasmvmtypes.UnsupportedRequest{Kind: "Stargate queries are disabled."}
307+
// RejectStargateQuerier rejects all stargate queries
308+
func RejectStargateQuerier() func(ctx sdk.Context, request *wasmvmtypes.StargateQuery) ([]byte, error) {
309+
return func(ctx sdk.Context, request *wasmvmtypes.StargateQuery) ([]byte, error) {
310+
return nil, wasmvmtypes.UnsupportedRequest{Kind: "Stargate queries are disabled"}
311+
}
312+
}
313+
314+
// AcceptedStargateQueries define accepted Stargate queries as a map with path as key and response type as value.
315+
// For example:
316+
// acceptList["/cosmos.auth.v1beta1.Query/Account"]= &authtypes.QueryAccountResponse{}
317+
type AcceptedStargateQueries map[string]codec.ProtoMarshaler
318+
319+
// AcceptListStargateQuerier supports a preconfigured set of stargate queries only.
320+
// All arguments must be non nil.
321+
//
322+
// Warning: Chains need to test and maintain their accept list carefully.
323+
// There were critical consensus breaking issues in the past with non-deterministic behaviour in the SDK.
324+
//
325+
// This queries can be set via WithQueryPlugins option in the wasm keeper constructor:
326+
// WithQueryPlugins(&QueryPlugins{Stargate: AcceptListStargateQuerier(acceptList, queryRouter, codec)})
327+
func AcceptListStargateQuerier(acceptList AcceptedStargateQueries, queryRouter GRPCQueryRouter, codec codec.Codec) func(ctx sdk.Context, request *wasmvmtypes.StargateQuery) ([]byte, error) {
328+
return func(ctx sdk.Context, request *wasmvmtypes.StargateQuery) ([]byte, error) {
329+
protoResponse, accepted := acceptList[request.Path]
330+
if !accepted {
331+
return nil, wasmvmtypes.UnsupportedRequest{Kind: fmt.Sprintf("'%s' path is not allowed from the contract", request.Path)}
332+
}
333+
334+
route := queryRouter.Route(request.Path)
335+
if route == nil {
336+
return nil, wasmvmtypes.UnsupportedRequest{Kind: fmt.Sprintf("No route to query '%s'", request.Path)}
337+
}
338+
339+
res, err := route(ctx, abci.RequestQuery{
340+
Data: request.Data,
341+
Path: request.Path,
342+
})
343+
if err != nil {
344+
return nil, err
345+
}
346+
347+
return ConvertProtoToJSONMarshal(codec, protoResponse, res.Value)
308348
}
309349
}
310350

@@ -551,6 +591,24 @@ func ConvertSdkCoinToWasmCoin(coin sdk.Coin) wasmvmtypes.Coin {
551591
}
552592
}
553593

594+
// ConvertProtoToJSONMarshal unmarshals the given bytes into a proto message and then marshals it to json.
595+
// This is done so that clients calling stargate queries do not need to define their own proto unmarshalers,
596+
// being able to use response directly by json marshalling, which is supported in cosmwasm.
597+
func ConvertProtoToJSONMarshal(cdc codec.Codec, protoResponse codec.ProtoMarshaler, bz []byte) ([]byte, error) {
598+
// unmarshal binary into stargate response data structure
599+
err := cdc.Unmarshal(bz, protoResponse)
600+
if err != nil {
601+
return nil, sdkerrors.Wrap(err, "to proto")
602+
}
603+
604+
bz, err = cdc.MarshalJSON(protoResponse)
605+
if err != nil {
606+
return nil, sdkerrors.Wrap(err, "to json")
607+
}
608+
609+
return bz, nil
610+
}
611+
554612
var _ WasmVMQueryHandler = WasmVMQueryHandlerFn(nil)
555613

556614
// WasmVMQueryHandlerFn is a helper to construct a function based query handler.

0 commit comments

Comments
 (0)