mukan-ibc/modules/light-clients/08-wasm/keeper/querier.go
Mukan Erkin Törük 88dd97a9f8
Some checks failed
CodeQL / Analyze (push) Waiting to run
golangci-lint / lint (push) Waiting to run
Tests / Code Coverage / build (amd64) (push) Waiting to run
Tests / Code Coverage / build (arm64) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[additional-args:-tags="test_e2e" name:e2e path:./e2e]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:08-wasm path:./modules/light-clients/08-wasm]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:ibc-go path:.]) (push) Waiting to run
Docker Build & Push Simapp (main) / docker-build (push) Has been cancelled
refactor: replace all github.com upstream refs with git.cw.tr/mukan-network
2026-05-11 03:36:22 +03:00

182 lines
5.7 KiB
Go

package keeper
import (
"encoding/json"
"fmt"
"slices"
wasmvmtypes "github.com/CosmWasm/wasmvm/v2/types"
errorsmod "cosmossdk.io/errors"
storetypes "cosmossdk.io/store/types"
sdk "git.cw.tr/mukan-network/mukan-sdk/types"
abci "git.cw.tr/mukan-network/mukan-consensus/abci/types"
"github.com/cosmos/ibc-go/modules/light-clients/08-wasm/v10/types"
)
/*
`queryHandler` is a contextual querier which references the global `ibcwasm.QueryPluginsI`
to handle queries. The global `ibcwasm.QueryPluginsI` points to a `types.QueryPlugins` which
contains two sub-queriers: `types.CustomQuerier` and `types.StargateQuerier`. These sub-queriers
can be replaced by the user through the options api in the keeper.
In addition, the `types.StargateQuerier` references a global `types.QueryRouter` which points
to `baseapp.GRPCQueryRouter`.
This design is based on wasmd's (v0.50.0) querier plugin design.
*/
var _ wasmvmtypes.Querier = (*queryHandler)(nil)
// defaultAcceptList defines a set of default allowed queries made available to the Querier.
var defaultAcceptList = []string{
"/ibc.core.client.v1.Query/VerifyMembership",
}
// queryHandler is a wrapper around the sdk.Context and the CallerID that calls
// into the query plugins.
type queryHandler struct {
Ctx sdk.Context
Plugins QueryPlugins
CallerID string
}
// newQueryHandler returns a default querier that can be used in the contract.
func newQueryHandler(ctx sdk.Context, plugins QueryPlugins, callerID string) *queryHandler {
return &queryHandler{
Ctx: ctx,
Plugins: plugins,
CallerID: callerID,
}
}
// GasConsumed implements the wasmvmtypes.Querier interface.
func (q *queryHandler) GasConsumed() uint64 {
return VMGasRegister.ToWasmVMGas(q.Ctx.GasMeter().GasConsumed())
}
// Query implements the wasmvmtypes.Querier interface.
func (q *queryHandler) Query(request wasmvmtypes.QueryRequest, gasLimit uint64) ([]byte, error) {
sdkGas := VMGasRegister.FromWasmVMGas(gasLimit)
// discard all changes/events in subCtx by not committing the cached context
subCtx, _ := q.Ctx.WithGasMeter(storetypes.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")
}()
res, err := q.Plugins.HandleQuery(subCtx, q.CallerID, request)
if err == nil {
return res, nil
}
moduleLogger(q.Ctx).Debug("Redacting query error", "cause", err)
return nil, redactError(err)
}
type (
CustomQuerier func(ctx sdk.Context, request json.RawMessage) ([]byte, error)
StargateQuerier func(ctx sdk.Context, request *wasmvmtypes.StargateQuery) ([]byte, error)
// QueryPlugins is a list of queriers that can be used to extend the default querier.
QueryPlugins struct {
Custom CustomQuerier
Stargate StargateQuerier
}
)
// Merge merges the query plugin with a provided one.
func (e QueryPlugins) Merge(x *QueryPlugins) QueryPlugins {
// only update if this is non-nil and then only set values
if x == nil {
return e
}
if x.Custom != nil {
e.Custom = x.Custom
}
if x.Stargate != nil {
e.Stargate = x.Stargate
}
return e
}
// HandleQuery implements the ibcwasm.QueryPluginsI interface.
func (e QueryPlugins) HandleQuery(ctx sdk.Context, caller string, request wasmvmtypes.QueryRequest) ([]byte, error) {
if request.Stargate != nil {
return e.Stargate(ctx, request.Stargate)
}
if request.Custom != nil {
return e.Custom(ctx, request.Custom)
}
return nil, wasmvmtypes.UnsupportedRequest{Kind: "Unsupported query request"}
}
// NewDefaultQueryPlugins returns the default set of query plugins
func NewDefaultQueryPlugins(queryRouter types.QueryRouter) QueryPlugins {
return QueryPlugins{
Custom: RejectCustomQuerier(),
Stargate: AcceptListStargateQuerier([]string{}, queryRouter),
}
}
// AcceptListStargateQuerier allows all queries that are in the provided accept list.
// This function returns protobuf encoded responses in bytes.
func AcceptListStargateQuerier(acceptedQueries []string, queryRouter types.QueryRouter) func(sdk.Context, *wasmvmtypes.StargateQuery) ([]byte, error) {
return func(ctx sdk.Context, request *wasmvmtypes.StargateQuery) ([]byte, error) {
// append user defined accepted queries to default list defined above.
acceptedQueries = append(defaultAcceptList, acceptedQueries...)
isAccepted := slices.Contains(acceptedQueries, request.Path)
if !isAccepted {
return nil, wasmvmtypes.UnsupportedRequest{Kind: fmt.Sprintf("'%s' path is not allowed from the contract", request.Path)}
}
route := queryRouter.Route(request.Path)
if route == nil {
return nil, wasmvmtypes.UnsupportedRequest{Kind: fmt.Sprintf("No route to query '%s'", request.Path)}
}
res, err := route(ctx, &abci.RequestQuery{
Data: request.Data,
Path: request.Path,
})
if err != nil {
return nil, err
}
if res == nil || res.Value == nil {
return nil, wasmvmtypes.InvalidResponse{Err: "Query response is empty"}
}
return res.Value, nil
}
}
// RejectCustomQuerier rejects all custom queries
func RejectCustomQuerier() func(sdk.Context, json.RawMessage) ([]byte, error) {
return func(ctx sdk.Context, request json.RawMessage) ([]byte, error) {
return nil, wasmvmtypes.UnsupportedRequest{Kind: "Custom queries are not allowed"}
}
}
// Wasmd Issue [#759](https://github.com/CosmWasm/wasmd/issues/759)
// Don't return error string for worries of non-determinism
func redactError(err error) error {
// Do not redact system errors
// SystemErrors must be created in 08-wasm and we can ensure determinism
if wasmvmtypes.ToSystemError(err) != nil {
return err
}
codespace, code, _ := errorsmod.ABCIInfo(err, false)
return fmt.Errorf("codespace: %s, code: %d", codespace, code)
}