97 lines
3.1 KiB
Go
97 lines
3.1 KiB
Go
package util
|
|
|
|
import (
|
|
"regexp"
|
|
"runtime/debug"
|
|
"strings"
|
|
|
|
cosmos_proto "github.com/cosmos/cosmos-proto"
|
|
"google.golang.org/protobuf/proto"
|
|
"google.golang.org/protobuf/reflect/protoreflect"
|
|
"google.golang.org/protobuf/reflect/protoregistry"
|
|
"google.golang.org/protobuf/types/dynamicpb"
|
|
|
|
"cosmossdk.io/client/v2/internal/strcase"
|
|
)
|
|
|
|
// get build info to verify later if comment is supported
|
|
// this is a hack in because of the global api module package
|
|
// later versions unsupported by the current version can be added
|
|
var buildInfo, _ = debug.ReadBuildInfo()
|
|
|
|
// DescriptorKebabName returns the name of the descriptor in kebab case.
|
|
func DescriptorKebabName(descriptor protoreflect.Descriptor) string {
|
|
return strcase.ToKebab(string(descriptor.Name()))
|
|
}
|
|
|
|
func ResolveMessageType(resolver protoregistry.MessageTypeResolver, descriptor protoreflect.MessageDescriptor) protoreflect.MessageType {
|
|
typ, err := resolver.FindMessageByName(descriptor.FullName())
|
|
if err == nil {
|
|
return typ
|
|
}
|
|
|
|
return dynamicpb.NewMessageType(descriptor)
|
|
}
|
|
|
|
// IsSupportedVersion is used to determine in which version of a module / sdk a rpc was introduced.
|
|
// It returns false if the rpc has comment for an higher version than the current one.
|
|
// It returns true if the method descriptor contains no annotation.
|
|
func IsSupportedVersion(methodDesc protoreflect.MethodDescriptor) bool {
|
|
return isSupportedVersion(methodDesc, buildInfo)
|
|
}
|
|
|
|
// isSupportedVersion is used to determine in which version of a module / sdk a rpc was introduced.
|
|
// It returns false if the rpc has comment for an higher version than the current one.
|
|
// It returns true if the method descriptor contains no annotation.
|
|
// It takes a buildInfo as argument to be able to test it.
|
|
func isSupportedVersion(methodDesc protoreflect.MethodDescriptor, buildInfo *debug.BuildInfo) bool {
|
|
hasVersion := proto.HasExtension(methodDesc.Options(), cosmos_proto.E_MethodAddedIn)
|
|
if !hasVersion || buildInfo == nil || len(buildInfo.Deps) == 0 {
|
|
return true
|
|
}
|
|
|
|
version := proto.GetExtension(methodDesc.Options(), cosmos_proto.E_MethodAddedIn).(string)
|
|
moduleName, version := parseVersion(version)
|
|
if moduleName == "" || version == "" {
|
|
return true // if no comment consider it's supported
|
|
}
|
|
|
|
for _, dep := range buildInfo.Deps {
|
|
if !strings.Contains(dep.Path, moduleName) {
|
|
continue
|
|
}
|
|
|
|
return version <= dep.Version
|
|
}
|
|
|
|
// if cannot find the module consider it isn't supported
|
|
// for instance the x/gov module wasn't extracted in v0.50
|
|
// so it isn't present in the build info, however, that means
|
|
// it isn't supported in v0.50.
|
|
return false
|
|
}
|
|
|
|
var sinceCommentRegex = regexp.MustCompile(`(\S+) (\S+)`)
|
|
|
|
// parseVersion parses the `cosmos-sdk v0.xx` comment on rpc.
|
|
func parseVersion(input string) (string, string) {
|
|
var (
|
|
moduleName string
|
|
version string
|
|
)
|
|
|
|
input = strings.ToLower(input)
|
|
input = strings.ReplaceAll(input, "cosmos sdk", "cosmos-sdk")
|
|
|
|
matches := sinceCommentRegex.FindStringSubmatch(input)
|
|
if len(matches) >= 3 {
|
|
moduleName, version = strings.TrimPrefix(matches[1], "x/"), matches[2]
|
|
|
|
if !strings.HasPrefix(version, "v") {
|
|
version = "v" + version
|
|
}
|
|
}
|
|
|
|
return moduleName, version
|
|
}
|