github.com/cosmos/cosmos-sdk@v0.50.10/runtime/module.go (about)

     1  package runtime
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  
     7  	"github.com/cosmos/gogoproto/proto"
     8  	"google.golang.org/protobuf/reflect/protodesc"
     9  	"google.golang.org/protobuf/reflect/protoregistry"
    10  
    11  	runtimev1alpha1 "cosmossdk.io/api/cosmos/app/runtime/v1alpha1"
    12  	appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1"
    13  	authmodulev1 "cosmossdk.io/api/cosmos/auth/module/v1"
    14  	stakingmodulev1 "cosmossdk.io/api/cosmos/staking/module/v1"
    15  	"cosmossdk.io/core/address"
    16  	"cosmossdk.io/core/appmodule"
    17  	"cosmossdk.io/core/comet"
    18  	"cosmossdk.io/core/event"
    19  	"cosmossdk.io/core/genesis"
    20  	"cosmossdk.io/core/header"
    21  	"cosmossdk.io/core/store"
    22  	"cosmossdk.io/depinject"
    23  	"cosmossdk.io/log"
    24  	storetypes "cosmossdk.io/store/types"
    25  	"cosmossdk.io/x/tx/signing"
    26  
    27  	"github.com/cosmos/cosmos-sdk/baseapp"
    28  	"github.com/cosmos/cosmos-sdk/codec"
    29  	addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
    30  	codectypes "github.com/cosmos/cosmos-sdk/codec/types"
    31  	"github.com/cosmos/cosmos-sdk/std"
    32  	"github.com/cosmos/cosmos-sdk/types/module"
    33  	"github.com/cosmos/cosmos-sdk/types/msgservice"
    34  )
    35  
    36  type appModule struct {
    37  	app *App
    38  }
    39  
    40  func (m appModule) RegisterServices(configurator module.Configurator) {
    41  	err := m.app.registerRuntimeServices(configurator)
    42  	if err != nil {
    43  		panic(err)
    44  	}
    45  }
    46  
    47  func (m appModule) IsOnePerModuleType() {}
    48  func (m appModule) IsAppModule()        {}
    49  
    50  var (
    51  	_ appmodule.AppModule = appModule{}
    52  	_ module.HasServices  = appModule{}
    53  )
    54  
    55  // BaseAppOption is a depinject.AutoGroupType which can be used to pass
    56  // BaseApp options into the depinject. It should be used carefully.
    57  type BaseAppOption func(*baseapp.BaseApp)
    58  
    59  // IsManyPerContainerType indicates that this is a depinject.ManyPerContainerType.
    60  func (b BaseAppOption) IsManyPerContainerType() {}
    61  
    62  func init() {
    63  	appmodule.Register(&runtimev1alpha1.Module{},
    64  		appmodule.Provide(
    65  			ProvideApp,
    66  			ProvideInterfaceRegistry,
    67  			ProvideKVStoreKey,
    68  			ProvideTransientStoreKey,
    69  			ProvideMemoryStoreKey,
    70  			ProvideGenesisTxHandler,
    71  			ProvideKVStoreService,
    72  			ProvideMemoryStoreService,
    73  			ProvideTransientStoreService,
    74  			ProvideEventService,
    75  			ProvideHeaderInfoService,
    76  			ProvideCometInfoService,
    77  			ProvideBasicManager,
    78  			ProvideAddressCodec,
    79  		),
    80  		appmodule.Invoke(SetupAppBuilder),
    81  	)
    82  }
    83  
    84  func ProvideApp(interfaceRegistry codectypes.InterfaceRegistry) (
    85  	codec.Codec,
    86  	*codec.LegacyAmino,
    87  	*AppBuilder,
    88  	*baseapp.MsgServiceRouter,
    89  	*baseapp.GRPCQueryRouter,
    90  	appmodule.AppModule,
    91  	protodesc.Resolver,
    92  	protoregistry.MessageTypeResolver,
    93  	error,
    94  ) {
    95  	protoFiles := proto.HybridResolver
    96  	protoTypes := protoregistry.GlobalTypes
    97  
    98  	// At startup, check that all proto annotations are correct.
    99  	if err := msgservice.ValidateProtoAnnotations(protoFiles); err != nil {
   100  		// Once we switch to using protoreflect-based ante handlers, we might
   101  		// want to panic here instead of logging a warning.
   102  		_, _ = fmt.Fprintln(os.Stderr, err.Error())
   103  	}
   104  
   105  	amino := codec.NewLegacyAmino()
   106  
   107  	std.RegisterInterfaces(interfaceRegistry)
   108  	std.RegisterLegacyAminoCodec(amino)
   109  
   110  	cdc := codec.NewProtoCodec(interfaceRegistry)
   111  	msgServiceRouter := baseapp.NewMsgServiceRouter()
   112  	grpcQueryRouter := baseapp.NewGRPCQueryRouter()
   113  	app := &App{
   114  		storeKeys:         nil,
   115  		interfaceRegistry: interfaceRegistry,
   116  		cdc:               cdc,
   117  		amino:             amino,
   118  		basicManager:      module.BasicManager{},
   119  		msgServiceRouter:  msgServiceRouter,
   120  		grpcQueryRouter:   grpcQueryRouter,
   121  	}
   122  	appBuilder := &AppBuilder{app}
   123  
   124  	return cdc, amino, appBuilder, msgServiceRouter, grpcQueryRouter, appModule{app}, protoFiles, protoTypes, nil
   125  }
   126  
   127  type AppInputs struct {
   128  	depinject.In
   129  
   130  	AppConfig          *appv1alpha1.Config `optional:"true"`
   131  	Config             *runtimev1alpha1.Module
   132  	AppBuilder         *AppBuilder
   133  	Modules            map[string]appmodule.AppModule
   134  	CustomModuleBasics map[string]module.AppModuleBasic `optional:"true"`
   135  	BaseAppOptions     []BaseAppOption
   136  	InterfaceRegistry  codectypes.InterfaceRegistry
   137  	LegacyAmino        *codec.LegacyAmino
   138  	Logger             log.Logger
   139  }
   140  
   141  func SetupAppBuilder(inputs AppInputs) {
   142  	app := inputs.AppBuilder.app
   143  	app.baseAppOptions = inputs.BaseAppOptions
   144  	app.config = inputs.Config
   145  	app.appConfig = inputs.AppConfig
   146  	app.logger = inputs.Logger
   147  	app.ModuleManager = module.NewManagerFromMap(inputs.Modules)
   148  
   149  	for name, mod := range inputs.Modules {
   150  		if customBasicMod, ok := inputs.CustomModuleBasics[name]; ok {
   151  			app.basicManager[name] = customBasicMod
   152  			customBasicMod.RegisterInterfaces(inputs.InterfaceRegistry)
   153  			customBasicMod.RegisterLegacyAminoCodec(inputs.LegacyAmino)
   154  			continue
   155  		}
   156  
   157  		coreAppModuleBasic := module.CoreAppModuleBasicAdaptor(name, mod)
   158  		app.basicManager[name] = coreAppModuleBasic
   159  		coreAppModuleBasic.RegisterInterfaces(inputs.InterfaceRegistry)
   160  		coreAppModuleBasic.RegisterLegacyAminoCodec(inputs.LegacyAmino)
   161  	}
   162  }
   163  
   164  func ProvideInterfaceRegistry(addressCodec address.Codec, validatorAddressCodec ValidatorAddressCodec, customGetSigners []signing.CustomGetSigner) (codectypes.InterfaceRegistry, error) {
   165  	signingOptions := signing.Options{
   166  		AddressCodec:          addressCodec,
   167  		ValidatorAddressCodec: validatorAddressCodec,
   168  	}
   169  	for _, signer := range customGetSigners {
   170  		signingOptions.DefineCustomGetSigners(signer.MsgType, signer.Fn)
   171  	}
   172  
   173  	interfaceRegistry, err := codectypes.NewInterfaceRegistryWithOptions(codectypes.InterfaceRegistryOptions{
   174  		ProtoFiles:     proto.HybridResolver,
   175  		SigningOptions: signingOptions,
   176  	})
   177  	if err != nil {
   178  		return nil, err
   179  	}
   180  
   181  	if err := interfaceRegistry.SigningContext().Validate(); err != nil {
   182  		return nil, err
   183  	}
   184  
   185  	return interfaceRegistry, nil
   186  }
   187  
   188  func registerStoreKey(wrapper *AppBuilder, key storetypes.StoreKey) {
   189  	wrapper.app.storeKeys = append(wrapper.app.storeKeys, key)
   190  }
   191  
   192  func storeKeyOverride(config *runtimev1alpha1.Module, moduleName string) *runtimev1alpha1.StoreKeyConfig {
   193  	for _, cfg := range config.OverrideStoreKeys {
   194  		if cfg.ModuleName == moduleName {
   195  			return cfg
   196  		}
   197  	}
   198  	return nil
   199  }
   200  
   201  func ProvideKVStoreKey(config *runtimev1alpha1.Module, key depinject.ModuleKey, app *AppBuilder) *storetypes.KVStoreKey {
   202  	override := storeKeyOverride(config, key.Name())
   203  
   204  	var storeKeyName string
   205  	if override != nil {
   206  		storeKeyName = override.KvStoreKey
   207  	} else {
   208  		storeKeyName = key.Name()
   209  	}
   210  
   211  	storeKey := storetypes.NewKVStoreKey(storeKeyName)
   212  	registerStoreKey(app, storeKey)
   213  	return storeKey
   214  }
   215  
   216  func ProvideTransientStoreKey(key depinject.ModuleKey, app *AppBuilder) *storetypes.TransientStoreKey {
   217  	storeKey := storetypes.NewTransientStoreKey(fmt.Sprintf("transient:%s", key.Name()))
   218  	registerStoreKey(app, storeKey)
   219  	return storeKey
   220  }
   221  
   222  func ProvideMemoryStoreKey(key depinject.ModuleKey, app *AppBuilder) *storetypes.MemoryStoreKey {
   223  	storeKey := storetypes.NewMemoryStoreKey(fmt.Sprintf("memory:%s", key.Name()))
   224  	registerStoreKey(app, storeKey)
   225  	return storeKey
   226  }
   227  
   228  func ProvideGenesisTxHandler(appBuilder *AppBuilder) genesis.TxHandler {
   229  	return appBuilder.app
   230  }
   231  
   232  func ProvideKVStoreService(config *runtimev1alpha1.Module, key depinject.ModuleKey, app *AppBuilder) store.KVStoreService {
   233  	storeKey := ProvideKVStoreKey(config, key, app)
   234  	return kvStoreService{key: storeKey}
   235  }
   236  
   237  func ProvideMemoryStoreService(key depinject.ModuleKey, app *AppBuilder) store.MemoryStoreService {
   238  	storeKey := ProvideMemoryStoreKey(key, app)
   239  	return memStoreService{key: storeKey}
   240  }
   241  
   242  func ProvideTransientStoreService(key depinject.ModuleKey, app *AppBuilder) store.TransientStoreService {
   243  	storeKey := ProvideTransientStoreKey(key, app)
   244  	return transientStoreService{key: storeKey}
   245  }
   246  
   247  func ProvideEventService() event.Service {
   248  	return EventService{}
   249  }
   250  
   251  func ProvideCometInfoService() comet.BlockInfoService {
   252  	return cometInfoService{}
   253  }
   254  
   255  func ProvideHeaderInfoService(app *AppBuilder) header.Service {
   256  	return headerInfoService{}
   257  }
   258  
   259  func ProvideBasicManager(app *AppBuilder) module.BasicManager {
   260  	return app.app.basicManager
   261  }
   262  
   263  type (
   264  	// ValidatorAddressCodec is an alias for address.Codec for validator addresses.
   265  	ValidatorAddressCodec address.Codec
   266  
   267  	// ConsensusAddressCodec is an alias for address.Codec for validator consensus addresses.
   268  	ConsensusAddressCodec address.Codec
   269  )
   270  
   271  type AddressCodecInputs struct {
   272  	depinject.In
   273  
   274  	AuthConfig    *authmodulev1.Module    `optional:"true"`
   275  	StakingConfig *stakingmodulev1.Module `optional:"true"`
   276  
   277  	AddressCodecFactory          func() address.Codec         `optional:"true"`
   278  	ValidatorAddressCodecFactory func() ValidatorAddressCodec `optional:"true"`
   279  	ConsensusAddressCodecFactory func() ConsensusAddressCodec `optional:"true"`
   280  }
   281  
   282  // ProvideAddressCodec provides an address.Codec to the container for any
   283  // modules that want to do address string <> bytes conversion.
   284  func ProvideAddressCodec(in AddressCodecInputs) (address.Codec, ValidatorAddressCodec, ConsensusAddressCodec) {
   285  	if in.AddressCodecFactory != nil && in.ValidatorAddressCodecFactory != nil && in.ConsensusAddressCodecFactory != nil {
   286  		return in.AddressCodecFactory(), in.ValidatorAddressCodecFactory(), in.ConsensusAddressCodecFactory()
   287  	}
   288  
   289  	if in.AuthConfig == nil || in.AuthConfig.Bech32Prefix == "" {
   290  		panic("auth config bech32 prefix cannot be empty if no custom address codec is provided")
   291  	}
   292  
   293  	if in.StakingConfig == nil {
   294  		in.StakingConfig = &stakingmodulev1.Module{}
   295  	}
   296  
   297  	if in.StakingConfig.Bech32PrefixValidator == "" {
   298  		in.StakingConfig.Bech32PrefixValidator = fmt.Sprintf("%svaloper", in.AuthConfig.Bech32Prefix)
   299  	}
   300  
   301  	if in.StakingConfig.Bech32PrefixConsensus == "" {
   302  		in.StakingConfig.Bech32PrefixConsensus = fmt.Sprintf("%svalcons", in.AuthConfig.Bech32Prefix)
   303  	}
   304  
   305  	return addresscodec.NewBech32Codec(in.AuthConfig.Bech32Prefix),
   306  		addresscodec.NewBech32Codec(in.StakingConfig.Bech32PrefixValidator),
   307  		addresscodec.NewBech32Codec(in.StakingConfig.Bech32PrefixConsensus)
   308  }