CosmWasm / wasmd

Basic cosmos-sdk app with web assembly smart contracts
Other
364 stars 386 forks source link

Feature request: Implement `module_query_safe` support #1840

Open srdtrk opened 4 months ago

srdtrk commented 4 months ago

Summary

The current default implementation of the stargate querier in CosmWasm rejects all queries. This results in chains creating individual whitelists of permissible queries using AcceptListStargateQuerier, leading to inconsistent experiences for users deploying contracts across different chains. A proposal is introduced to leverage the module_query_safe tag, introduced in CosmosSDK v0.47, to automatically generate a default whitelist of safe queries. This list, generated at module instantiation, would be merged with user-provided whitelists, ensuring deterministic, gas-consuming queries are permitted. The method for generating this whitelist involves iterating over proto files using proto reflection, an approach discussed and agreed upon with Binary Builders.

Problem Description

Currently, CosmWasm uses RejectStargateQuerier as its default query handling method due to the cosmos-sdk's limitations, where certain queries are either non-deterministic or do not consume gas as expected. Consequently, CosmWasm chains must each maintain a whitelist of acceptable queries through AcceptListStargateQuerier, complicating the deployment process for users on multiple chains.

Proposal

It's proposed to take advantage of the module_query_safe tag introduced in CosmosSDK v0.47. This tag identifies queries that are both deterministic and consume gas correctly, and are therefore safe to be called from within the state machine and CosmWasm. In CosmosSDK v0.50, almost all queries are marked with module_query_safe, for example, see bank queries.

The proposal suggests automatically generating a default whitelist of these safe queries at the module's inception. This list would then be combined with any user-defined whitelists to ensure only appropriate queries are allowed. The method for creating this whitelist involves iterating over proto files using proto reflection, a technique refined in collaboration with Binary Builders. I've been working on a similar feature for interchain accounts in https://github.com/cosmos/ibc-go/pull/5785 to allow module_query_safe queries in ICA. We currently generate this whitelist in NewKeeper using proto reflection:

func newModuleQuerySafeWhitelist() []string {
    // Create a whitelist of module safe queries
    whitelist := []string{}

    protoFiles, err := gogoproto.MergedRegistry()
    if err != nil {
        panic(err)
    }

    protoFiles.RangeFiles(func(fd protoreflect.FileDescriptor) bool {
        for i := 0; i < fd.Services().Len(); i++ {
            // Get the service descriptor
            sd := fd.Services().Get(i)

            // Skip services that are annotated with the "cosmos.msg.v1.service" option.
            if ext := proto.GetExtension(sd.Options(), msgv1.E_Service); ext != nil && ext.(bool) {
                continue
            }

            for j := 0; j < sd.Methods().Len(); j++ {
                // Get the method descriptor
                md := sd.Methods().Get(j)

                // Skip methods that are not annotated with the "cosmos.query.v1.module_query_safe" option.
                if ext := proto.GetExtension(md.Options(), queryv1.E_ModuleQuerySafe); ext == nil || !ext.(bool) {
                    continue
                }

                // Add the method to the whitelist
                whitelist = append(whitelist, fmt.Sprintf("/%s/%s", sd.FullName(), md.Name()))
            }
        }
        return true
    })

    return whitelist
}

We settled on this approach of iterating over all proto files to generate a whitelist after talking to Binary Builders.

Additional Use Cases:

This approach not only streamlines query handling but also opens avenues for further enhancements. For instance, it could simplify how CosmWasm associates method paths with query message type names, eliminating the need for specifying a method path alongside a proto Any. However, the details of implementing this additional feature fall beyond the scope of the current proposal.