github.com/cosmos/cosmos-sdk@v0.50.10/types/msgservice/validate.go (about)

     1  package msgservice
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	"google.golang.org/protobuf/proto"
     8  	"google.golang.org/protobuf/reflect/protoreflect"
     9  	"google.golang.org/protobuf/reflect/protoregistry"
    10  
    11  	msg "cosmossdk.io/api/cosmos/msg/v1"
    12  	"cosmossdk.io/x/tx/signing"
    13  )
    14  
    15  // ValidateAnnotations validates that the proto annotations are correct.
    16  // More specifically, it verifies:
    17  // - all services named "Msg" have `(cosmos.msg.v1.service) = true`,
    18  //
    19  // More validations can be added here in the future.
    20  //
    21  // If `protoFiles` is nil, then protoregistry.GlobalFile will be used.
    22  func ValidateProtoAnnotations(protoFiles signing.ProtoFileResolver) error {
    23  	if protoFiles == nil {
    24  		protoFiles = protoregistry.GlobalFiles
    25  	}
    26  
    27  	var serviceErrs []error
    28  	protoFiles.RangeFiles(func(fd protoreflect.FileDescriptor) bool {
    29  		for i := 0; i < fd.Services().Len(); i++ {
    30  			sd := fd.Services().Get(i)
    31  			if sd.Name() == "Msg" {
    32  				// We use the heuristic that services name Msg are exactly the
    33  				// ones that need the proto annotations check.
    34  				err := validateMsgServiceAnnotations(sd)
    35  				if err != nil {
    36  					serviceErrs = append(serviceErrs, err)
    37  				}
    38  			}
    39  		}
    40  
    41  		return true
    42  	})
    43  
    44  	return errors.Join(serviceErrs...)
    45  }
    46  
    47  // validateMsgServiceAnnotations validates that the service has the
    48  // `(cosmos.msg.v1.service) = true` proto annotation.
    49  func validateMsgServiceAnnotations(sd protoreflect.ServiceDescriptor) error {
    50  	ext := proto.GetExtension(sd.Options(), msg.E_Service)
    51  	isService, ok := ext.(bool)
    52  	if !ok {
    53  		return fmt.Errorf("expected bool, got %T", ext)
    54  	}
    55  
    56  	if !isService {
    57  		return fmt.Errorf("service %s does not have cosmos.msg.v1.service proto annotation", sd.FullName())
    58  	}
    59  
    60  	return nil
    61  }