diff --git a/wasmbinding/export_test.go b/wasmbinding/export_test.go new file mode 100644 index 0000000000000000000000000000000000000000..537dc1496e3d5a7e59dc243a5624b084cf6fe8e5 --- /dev/null +++ b/wasmbinding/export_test.go @@ -0,0 +1,7 @@ +package wasmbinding + +import "github.com/cosmos/cosmos-sdk/codec" + +func SetWhitelistedQuery(queryPath string, protoType codec.ProtoMarshaler) { + setWhitelistedQuery(queryPath, protoType) +} diff --git a/wasmbinding/query_plugin.go b/wasmbinding/query_plugin.go index b1f470d49afbd6be4f774be8977cd48126aa3317..2132ee98601f843215534c9974cf7495b5f511c2 100644 --- a/wasmbinding/query_plugin.go +++ b/wasmbinding/query_plugin.go @@ -15,11 +15,11 @@ import ( ) // StargateQuerier dispatches whitelisted stargate queries -func StargateQuerier(queryRouter baseapp.GRPCQueryRouter, codec codec.Codec) func(ctx sdk.Context, request *wasmvmtypes.StargateQuery) ([]byte, error) { +func StargateQuerier(queryRouter baseapp.GRPCQueryRouter, cdc codec.Codec) func(ctx sdk.Context, request *wasmvmtypes.StargateQuery) ([]byte, error) { return func(ctx sdk.Context, request *wasmvmtypes.StargateQuery) ([]byte, error) { - protoResponse, whitelisted := StargateWhitelist.Load(request.Path) - if !whitelisted { - return nil, wasmvmtypes.UnsupportedRequest{Kind: fmt.Sprintf("'%s' path is not allowed from the contract", request.Path)} + protoResponseType, err := GetWhitelistedQuery(request.Path) + if err != nil { + return nil, err } route := queryRouter.Route(request.Path) @@ -35,7 +35,7 @@ func StargateQuerier(queryRouter baseapp.GRPCQueryRouter, codec codec.Codec) fun return nil, err } - bz, err := ConvertProtoToJSONMarshal(protoResponse, res.Value, codec) + bz, err := ConvertProtoToJSONMarshal(protoResponseType, res.Value, cdc) if err != nil { return nil, err } @@ -174,25 +174,19 @@ func CustomQuerier(qp *QueryPlugin) func(ctx sdk.Context, request json.RawMessag // ConvertProtoToJsonMarshal unmarshals the given bytes into a proto message and then marshals it to json. // This is done so that clients calling stargate queries do not need to define their own proto unmarshalers, // being able to use response directly by json marshalling, which is supported in cosmwasm. -func ConvertProtoToJSONMarshal(protoResponse interface{}, bz []byte, cdc codec.Codec) ([]byte, error) { - // all values are proto message - message, ok := protoResponse.(codec.ProtoMarshaler) - if !ok { - return nil, wasmvmtypes.Unknown{} - } - +func ConvertProtoToJSONMarshal(protoResponseType codec.ProtoMarshaler, bz []byte, cdc codec.Codec) ([]byte, error) { // unmarshal binary into stargate response data structure - err := cdc.Unmarshal(bz, message) + err := cdc.Unmarshal(bz, protoResponseType) if err != nil { return nil, wasmvmtypes.Unknown{} } - bz, err = cdc.MarshalJSON(message) + bz, err = cdc.MarshalJSON(protoResponseType) if err != nil { return nil, wasmvmtypes.Unknown{} } - message.Reset() + protoResponseType.Reset() return bz, nil } diff --git a/wasmbinding/query_plugin_test.go b/wasmbinding/query_plugin_test.go index ff11dd1154f4b14cd1e6e1bb4be6339339ac0786..2cf9281291f5e37e6ddd00752605f757a70aabdc 100644 --- a/wasmbinding/query_plugin_test.go +++ b/wasmbinding/query_plugin_test.go @@ -7,6 +7,7 @@ import ( "time" wasmvmtypes "github.com/CosmWasm/wasmvm/types" + "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" @@ -16,7 +17,6 @@ import ( proto "github.com/golang/protobuf/proto" "github.com/stretchr/testify/suite" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - "google.golang.org/protobuf/runtime/protoiface" "github.com/osmosis-labs/osmosis/v12/app" epochtypes "github.com/osmosis-labs/osmosis/v12/x/epochs/types" @@ -84,7 +84,7 @@ func (suite *StargateTestSuite) TestStargateQuerier() { // fund account to recieve non-empty response simapp.FundAccount(suite.app.BankKeeper, suite.ctx, accAddr, sdk.Coins{sdk.NewCoin("stake", sdk.NewInt(10))}) - wasmbinding.StargateWhitelist.Store("/cosmos.bank.v1beta1.Query/AllBalances", &banktypes.QueryAllBalancesResponse{}) + wasmbinding.SetWhitelistedQuery("/cosmos.bank.v1beta1.Query/AllBalances", &banktypes.QueryAllBalancesResponse{}) }, path: "/cosmos.bank.v1beta1.Query/AllBalances", requestData: func() []byte { @@ -106,7 +106,7 @@ func (suite *StargateTestSuite) TestStargateQuerier() { // fund account to recieve non-empty response simapp.FundAccount(suite.app.BankKeeper, suite.ctx, accAddr, sdk.Coins{sdk.NewCoin("stake", sdk.NewInt(10))}) - wasmbinding.StargateWhitelist.Store("/cosmos.bank.v1beta1.Query/AllBalances", &banktypes.QueryAllBalancesResponse{}) + wasmbinding.SetWhitelistedQuery("/cosmos.bank.v1beta1.Query/AllBalances", &banktypes.QueryAllBalancesResponse{}) }, path: "/cosmos.bank.v1beta1.Query/AllBalances", requestData: func() []byte { @@ -123,7 +123,7 @@ func (suite *StargateTestSuite) TestStargateQuerier() { { name: "invalid query router route", testSetup: func() { - wasmbinding.StargateWhitelist.Store("invalid/query/router/route", epochtypes.QueryEpochsInfoRequest{}) + wasmbinding.SetWhitelistedQuery("invalid/query/router/route", &epochtypes.QueryEpochsInfoRequest{}) }, path: "invalid/query/router/route", requestData: func() []byte { @@ -147,7 +147,8 @@ func (suite *StargateTestSuite) TestStargateQuerier() { name: "error in unmarshalling response", // set up whitelist with wrong data testSetup: func() { - wasmbinding.StargateWhitelist.Store("/osmosis.epochs.v1beta1.Query/EpochInfos", interface{}(nil)) + wasmbinding.SetWhitelistedQuery("/osmosis.epochs.v1beta1.Query/EpochInfos", + &banktypes.QueryAllBalancesResponse{}) }, path: "/osmosis.epochs.v1beta1.Query/EpochInfos", requestData: func() []byte { @@ -160,7 +161,7 @@ func (suite *StargateTestSuite) TestStargateQuerier() { name: "error in grpc querier", // set up whitelist with wrong data testSetup: func() { - wasmbinding.StargateWhitelist.Store("/cosmos.bank.v1beta1.Query/AllBalances", banktypes.QueryAllBalancesRequest{}) + wasmbinding.SetWhitelistedQuery("/cosmos.bank.v1beta1.Query/AllBalances", &banktypes.QueryAllBalancesRequest{}) }, path: "/cosmos.bank.v1beta1.Query/AllBalances", requestData: func() []byte { @@ -191,20 +192,20 @@ func (suite *StargateTestSuite) TestStargateQuerier() { if tc.expectedQuerierError { suite.Require().Error(err) return - } else { - suite.Require().NoError(err) + } - protoResponse, ok := tc.responseProtoStruct.(proto.Message) - suite.Require().True(ok) + suite.Require().NoError(err) - // test correctness by unmarshalling json response into proto struct - err = suite.app.AppCodec().UnmarshalJSON(stargateResponse, protoResponse) - if tc.expectedUnMarshalError { - suite.Require().Error(err) - } else { - suite.Require().NoError(err) - suite.Require().NotNil(protoResponse) - } + protoResponse, ok := tc.responseProtoStruct.(proto.Message) + suite.Require().True(ok) + + // test correctness by unmarshalling json response into proto struct + err = suite.app.AppCodec().UnmarshalJSON(stargateResponse, protoResponse) + if tc.expectedUnMarshalError { + suite.Require().Error(err) + } else { + suite.Require().NoError(err) + suite.Require().NotNil(protoResponse) } if tc.resendRequest { @@ -225,9 +226,9 @@ func (suite *StargateTestSuite) TestConvertProtoToJsonMarshal() { testCases := []struct { name string queryPath string - protoResponseStruct proto.Message + protoResponseStruct codec.ProtoMarshaler originalResponse string - expectedProtoResponse proto.Message + expectedProtoResponse codec.ProtoMarshaler expectedError bool }{ { @@ -246,7 +247,7 @@ func (suite *StargateTestSuite) TestConvertProtoToJsonMarshal() { name: "invalid proto response struct", queryPath: "/cosmos.bank.v1beta1.Query/AllBalances", originalResponse: "0a090a036261721202333012050a03666f6f", - protoResponseStruct: protoiface.MessageV1(nil), + protoResponseStruct: &epochtypes.QueryCurrentEpochResponse{}, expectedError: true, }, } @@ -317,7 +318,7 @@ func (suite *StargateTestSuite) TestDeterministicJsonMarshal() { { "Query All Balances", func() { - wasmbinding.StargateWhitelist.Store("/cosmos.bank.v1beta1.Query/AllBalances", &banktypes.QueryAllBalancesResponse{}) + wasmbinding.SetWhitelistedQuery("/cosmos.bank.v1beta1.Query/AllBalances", &banktypes.QueryAllBalancesResponse{}) }, "0a090a036261721202333012050a03666f6f", "0a090a036261721202333012050a03666f6f1a2d636f736d6f73316a366a357473717571326a6c77326166376c3378656b796171377a67346c386a737566753738", @@ -380,8 +381,8 @@ func (suite *StargateTestSuite) TestDeterministicJsonMarshal() { tc.testSetup() } - binding, ok := wasmbinding.StargateWhitelist.Load(tc.queryPath) - suite.Require().True(ok) + binding, err := wasmbinding.GetWhitelistedQuery(tc.queryPath) + suite.Require().Nil(err) originVersionBz, err := hex.DecodeString(tc.originalResponse) suite.Require().NoError(err) diff --git a/wasmbinding/stargate_whitelist.go b/wasmbinding/stargate_whitelist.go index a82fda10a1c2fe0291e4593399ed9046de7f6f97..6b73131a4c5b6bbfc9cac573507945a81cce5e22 100644 --- a/wasmbinding/stargate_whitelist.go +++ b/wasmbinding/stargate_whitelist.go @@ -1,8 +1,11 @@ package wasmbinding import ( + "fmt" "sync" + wasmvmtypes "github.com/CosmWasm/wasmvm/types" + "github.com/cosmos/cosmos-sdk/codec" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" @@ -20,88 +23,106 @@ import ( txfeestypes "github.com/osmosis-labs/osmosis/v12/x/txfees/types" ) -// StargateWhitelist keeps whitelist and its deterministic +// stargateWhitelist keeps whitelist and its deterministic // response binding for stargate queries. // // The query can be multi-thread, so we have to use // thread safe sync.Map. -var StargateWhitelist sync.Map +var stargateWhitelist sync.Map func init() { // cosmos-sdk queries // auth - StargateWhitelist.Store("/cosmos.auth.v1beta1.Query/Account", &authtypes.QueryAccountResponse{}) - StargateWhitelist.Store("/cosmos.auth.v1beta1.Query/Params", &authtypes.QueryParamsResponse{}) + setWhitelistedQuery("/cosmos.auth.v1beta1.Query/Account", &authtypes.QueryAccountResponse{}) + setWhitelistedQuery("/cosmos.auth.v1beta1.Query/Params", &authtypes.QueryParamsResponse{}) // bank - StargateWhitelist.Store("/cosmos.bank.v1beta1.Query/Balance", &banktypes.QueryBalanceResponse{}) - StargateWhitelist.Store("/cosmos.bank.v1beta1.Query/DenomMetadata", &banktypes.QueryDenomsMetadataResponse{}) - StargateWhitelist.Store("/cosmos.bank.v1beta1.Query/Params", &banktypes.QueryParamsResponse{}) - StargateWhitelist.Store("/cosmos.bank.v1beta1.Query/SupplyOf", &banktypes.QuerySupplyOfResponse{}) + setWhitelistedQuery("/cosmos.bank.v1beta1.Query/Balance", &banktypes.QueryBalanceResponse{}) + setWhitelistedQuery("/cosmos.bank.v1beta1.Query/DenomMetadata", &banktypes.QueryDenomsMetadataResponse{}) + setWhitelistedQuery("/cosmos.bank.v1beta1.Query/Params", &banktypes.QueryParamsResponse{}) + setWhitelistedQuery("/cosmos.bank.v1beta1.Query/SupplyOf", &banktypes.QuerySupplyOfResponse{}) // distribution - StargateWhitelist.Store("/cosmos.distribution.v1beta1.Query/Params", &distributiontypes.QueryParamsResponse{}) - StargateWhitelist.Store("/cosmos.distribution.v1beta1.Query/DelegatorWithdrawAddress", &distributiontypes.QueryDelegatorWithdrawAddressResponse{}) - StargateWhitelist.Store("/cosmos.distribution.v1beta1.Query/ValidatorCommission", &distributiontypes.QueryValidatorCommissionResponse{}) + setWhitelistedQuery("/cosmos.distribution.v1beta1.Query/Params", &distributiontypes.QueryParamsResponse{}) + setWhitelistedQuery("/cosmos.distribution.v1beta1.Query/DelegatorWithdrawAddress", &distributiontypes.QueryDelegatorWithdrawAddressResponse{}) + setWhitelistedQuery("/cosmos.distribution.v1beta1.Query/ValidatorCommission", &distributiontypes.QueryValidatorCommissionResponse{}) // gov - StargateWhitelist.Store("/cosmos.gov.v1beta1.Query/Deposit", &govtypes.QueryDepositResponse{}) - StargateWhitelist.Store("/cosmos.gov.v1beta1.Query/Params", &govtypes.QueryParamsResponse{}) - StargateWhitelist.Store("/cosmos.gov.v1beta1.Query/Vote", &govtypes.QueryVoteResponse{}) + setWhitelistedQuery("/cosmos.gov.v1beta1.Query/Deposit", &govtypes.QueryDepositResponse{}) + setWhitelistedQuery("/cosmos.gov.v1beta1.Query/Params", &govtypes.QueryParamsResponse{}) + setWhitelistedQuery("/cosmos.gov.v1beta1.Query/Vote", &govtypes.QueryVoteResponse{}) // slashing - StargateWhitelist.Store("/cosmos.slashing.v1beta1.Query/Params", &slashingtypes.QueryParamsResponse{}) - StargateWhitelist.Store("/cosmos.slashing.v1beta1.Query/SigningInfo", &slashingtypes.QuerySigningInfoResponse{}) + setWhitelistedQuery("/cosmos.slashing.v1beta1.Query/Params", &slashingtypes.QueryParamsResponse{}) + setWhitelistedQuery("/cosmos.slashing.v1beta1.Query/SigningInfo", &slashingtypes.QuerySigningInfoResponse{}) // staking - StargateWhitelist.Store("/cosmos.staking.v1beta1.Query/Delegation", &stakingtypes.QueryDelegationResponse{}) - StargateWhitelist.Store("/cosmos.staking.v1beta1.Query/Params", &stakingtypes.QueryParamsResponse{}) - StargateWhitelist.Store("/cosmos.staking.v1beta1.Query/Validator", &stakingtypes.QueryValidatorResponse{}) + setWhitelistedQuery("/cosmos.staking.v1beta1.Query/Delegation", &stakingtypes.QueryDelegationResponse{}) + setWhitelistedQuery("/cosmos.staking.v1beta1.Query/Params", &stakingtypes.QueryParamsResponse{}) + setWhitelistedQuery("/cosmos.staking.v1beta1.Query/Validator", &stakingtypes.QueryValidatorResponse{}) // osmosis queries //epochs - StargateWhitelist.Store("/osmosis.epochs.v1beta1.Query/EpochInfos", &epochtypes.QueryEpochsInfoResponse{}) - StargateWhitelist.Store("/osmosis.epochs.v1beta1.Query/CurrentEpoch", &epochtypes.QueryCurrentEpochResponse{}) + setWhitelistedQuery("/osmosis.epochs.v1beta1.Query/EpochInfos", &epochtypes.QueryEpochsInfoResponse{}) + setWhitelistedQuery("/osmosis.epochs.v1beta1.Query/CurrentEpoch", &epochtypes.QueryCurrentEpochResponse{}) // gamm - StargateWhitelist.Store("/osmosis.gamm.v1beta1.Query/NumPools", &gammtypes.QueryNumPoolsResponse{}) - StargateWhitelist.Store("/osmosis.gamm.v1beta1.Query/TotalLiquidity", &gammtypes.QueryTotalLiquidityResponse{}) - StargateWhitelist.Store("/osmosis.gamm.v1beta1.Query/Pool", &gammtypes.QueryPoolResponse{}) - StargateWhitelist.Store("/osmosis.gamm.v1beta1.Query/PoolParams", &gammtypes.QueryPoolParamsResponse{}) - StargateWhitelist.Store("/osmosis.gamm.v1beta1.Query/TotalPoolLiquidity", &gammtypes.QueryTotalPoolLiquidityResponse{}) - StargateWhitelist.Store("/osmosis.gamm.v1beta1.Query/TotalShares", &gammtypes.QueryTotalSharesResponse{}) - StargateWhitelist.Store("/osmosis.gamm.v1beta1.Query/SpotPrice", &gammtypes.QuerySpotPriceResponse{}) + setWhitelistedQuery("/osmosis.gamm.v1beta1.Query/NumPools", &gammtypes.QueryNumPoolsResponse{}) + setWhitelistedQuery("/osmosis.gamm.v1beta1.Query/TotalLiquidity", &gammtypes.QueryTotalLiquidityResponse{}) + setWhitelistedQuery("/osmosis.gamm.v1beta1.Query/Pool", &gammtypes.QueryPoolResponse{}) + setWhitelistedQuery("/osmosis.gamm.v1beta1.Query/PoolParams", &gammtypes.QueryPoolParamsResponse{}) + setWhitelistedQuery("/osmosis.gamm.v1beta1.Query/TotalPoolLiquidity", &gammtypes.QueryTotalPoolLiquidityResponse{}) + setWhitelistedQuery("/osmosis.gamm.v1beta1.Query/TotalShares", &gammtypes.QueryTotalSharesResponse{}) + setWhitelistedQuery("/osmosis.gamm.v1beta1.Query/SpotPrice", &gammtypes.QuerySpotPriceResponse{}) // incentives - StargateWhitelist.Store("/osmosis.incentives.Query/ModuleToDistributeCoins", &incentivestypes.ModuleToDistributeCoinsResponse{}) - StargateWhitelist.Store("/osmosis.incentives.Query/ModuleDistributedCoins", &incentivestypes.ModuleDistributedCoinsResponse{}) - StargateWhitelist.Store("/osmosis.incentives.Query/LockableDurations", &incentivestypes.QueryLockableDurationsResponse{}) + setWhitelistedQuery("/osmosis.incentives.Query/ModuleToDistributeCoins", &incentivestypes.ModuleToDistributeCoinsResponse{}) + setWhitelistedQuery("/osmosis.incentives.Query/ModuleDistributedCoins", &incentivestypes.ModuleDistributedCoinsResponse{}) + setWhitelistedQuery("/osmosis.incentives.Query/LockableDurations", &incentivestypes.QueryLockableDurationsResponse{}) // lockup - StargateWhitelist.Store("/osmosis.lockup.Query/ModuleBalance", &lockuptypes.ModuleBalanceResponse{}) - StargateWhitelist.Store("/osmosis.lockup.Query/ModuleLockedAmount", &lockuptypes.ModuleLockedAmountResponse{}) - StargateWhitelist.Store("/osmosis.lockup.Query/AccountUnlockableCoins", &lockuptypes.AccountUnlockableCoinsResponse{}) - StargateWhitelist.Store("/osmosis.lockup.Query/AccountUnlockingCoins", &lockuptypes.AccountUnlockingCoinsResponse{}) - StargateWhitelist.Store("/osmosis.lockup.Query/LockedDenom", &lockuptypes.LockedDenomResponse{}) + setWhitelistedQuery("/osmosis.lockup.Query/ModuleBalance", &lockuptypes.ModuleBalanceResponse{}) + setWhitelistedQuery("/osmosis.lockup.Query/ModuleLockedAmount", &lockuptypes.ModuleLockedAmountResponse{}) + setWhitelistedQuery("/osmosis.lockup.Query/AccountUnlockableCoins", &lockuptypes.AccountUnlockableCoinsResponse{}) + setWhitelistedQuery("/osmosis.lockup.Query/AccountUnlockingCoins", &lockuptypes.AccountUnlockingCoinsResponse{}) + setWhitelistedQuery("/osmosis.lockup.Query/LockedDenom", &lockuptypes.LockedDenomResponse{}) // mint - StargateWhitelist.Store("/osmosis.mint.v1beta1.Query/EpochProvisions", &minttypes.QueryEpochProvisionsResponse{}) - StargateWhitelist.Store("/osmosis.mint.v1beta1.Query/Params", &minttypes.QueryParamsResponse{}) + setWhitelistedQuery("/osmosis.mint.v1beta1.Query/EpochProvisions", &minttypes.QueryEpochProvisionsResponse{}) + setWhitelistedQuery("/osmosis.mint.v1beta1.Query/Params", &minttypes.QueryParamsResponse{}) // pool-incentives - StargateWhitelist.Store("/osmosis.poolincentives.v1beta1.Query/GaugeIds", &poolincentivestypes.QueryGaugeIdsResponse{}) + setWhitelistedQuery("/osmosis.poolincentives.v1beta1.Query/GaugeIds", &poolincentivestypes.QueryGaugeIdsResponse{}) // superfluid - StargateWhitelist.Store("/osmosis.superfluid.Query/Params", &superfluidtypes.QueryParamsResponse{}) - StargateWhitelist.Store("/osmosis.superfluid.Query/AssetType", &superfluidtypes.AssetTypeResponse{}) - StargateWhitelist.Store("/osmosis.superfluid.Query/AllAssets", &superfluidtypes.AllAssetsResponse{}) - StargateWhitelist.Store("/osmosis.superfluid.Query/AssetMultiplier", &superfluidtypes.AssetMultiplierResponse{}) + setWhitelistedQuery("/osmosis.superfluid.Query/Params", &superfluidtypes.QueryParamsResponse{}) + setWhitelistedQuery("/osmosis.superfluid.Query/AssetType", &superfluidtypes.AssetTypeResponse{}) + setWhitelistedQuery("/osmosis.superfluid.Query/AllAssets", &superfluidtypes.AllAssetsResponse{}) + setWhitelistedQuery("/osmosis.superfluid.Query/AssetMultiplier", &superfluidtypes.AssetMultiplierResponse{}) // txfees - StargateWhitelist.Store("/osmosis.txfees.v1beta1.Query/FeeTokens", &txfeestypes.QueryFeeTokensResponse{}) - StargateWhitelist.Store("/osmosis.txfees.v1beta1.Query/DenomSpotPrice", &txfeestypes.QueryDenomSpotPriceResponse{}) - StargateWhitelist.Store("/osmosis.txfees.v1beta1.Query/DenomPoolId", &txfeestypes.QueryDenomPoolIdResponse{}) - StargateWhitelist.Store("/osmosis.txfees.v1beta1.Query/BaseDenom", &txfeestypes.QueryBaseDenomResponse{}) + setWhitelistedQuery("/osmosis.txfees.v1beta1.Query/FeeTokens", &txfeestypes.QueryFeeTokensResponse{}) + setWhitelistedQuery("/osmosis.txfees.v1beta1.Query/DenomSpotPrice", &txfeestypes.QueryDenomSpotPriceResponse{}) + setWhitelistedQuery("/osmosis.txfees.v1beta1.Query/DenomPoolId", &txfeestypes.QueryDenomPoolIdResponse{}) + setWhitelistedQuery("/osmosis.txfees.v1beta1.Query/BaseDenom", &txfeestypes.QueryBaseDenomResponse{}) +} + +// GetWhitelistedQuery returns the whitelisted query at the provided path. +// If the query does not exist, or it was setup wrong by the chain, this returns an error. +func GetWhitelistedQuery(queryPath string) (codec.ProtoMarshaler, error) { + protoResponseAny, isWhitelisted := stargateWhitelist.Load(queryPath) + if !isWhitelisted { + return nil, wasmvmtypes.UnsupportedRequest{Kind: fmt.Sprintf("'%s' path is not allowed from the contract", queryPath)} + } + protoResponseType, ok := protoResponseAny.(codec.ProtoMarshaler) + if !ok { + return nil, wasmvmtypes.Unknown{} + } + return protoResponseType, nil +} + +func setWhitelistedQuery(queryPath string, protoType codec.ProtoMarshaler) { + stargateWhitelist.Store(queryPath, protoType) }