github.com/Finschia/finschia-sdk@v0.48.1/types/module/module.go (about)

     1  /*
     2  Package module contains application module patterns and associated "manager" functionality.
     3  The module pattern has been broken down by:
     4    - independent module functionality (AppModuleBasic)
     5    - inter-dependent module genesis functionality (AppModuleGenesis)
     6    - inter-dependent module simulation functionality (AppModuleSimulation)
     7    - inter-dependent module full functionality (AppModule)
     8  
     9  inter-dependent module functionality is module functionality which somehow
    10  depends on other modules, typically through the module keeper.  Many of the
    11  module keepers are dependent on each other, thus in order to access the full
    12  set of module functionality we need to define all the keepers/params-store/keys
    13  etc. This full set of advanced functionality is defined by the AppModule interface.
    14  
    15  Independent module functions are separated to allow for the construction of the
    16  basic application structures required early on in the application definition
    17  and used to enable the definition of full module functionality later in the
    18  process. This separation is necessary, however we still want to allow for a
    19  high level pattern for modules to follow - for instance, such that we don't
    20  have to manually register all of the codecs for all the modules. This basic
    21  procedure as well as other basic patterns are handled through the use of
    22  BasicManager.
    23  
    24  Lastly the interface for genesis functionality (AppModuleGenesis) has been
    25  separated out from full module functionality (AppModule) so that modules which
    26  are only used for genesis can take advantage of the Module patterns without
    27  needlessly defining many placeholder functions
    28  */
    29  package module
    30  
    31  import (
    32  	"encoding/json"
    33  	"fmt"
    34  	"sort"
    35  
    36  	"github.com/grpc-ecosystem/grpc-gateway/runtime"
    37  	"github.com/spf13/cobra"
    38  
    39  	ocabci "github.com/Finschia/ostracon/abci/types"
    40  	abci "github.com/tendermint/tendermint/abci/types"
    41  
    42  	"github.com/Finschia/finschia-sdk/client"
    43  	"github.com/Finschia/finschia-sdk/codec"
    44  	codectypes "github.com/Finschia/finschia-sdk/codec/types"
    45  	sdk "github.com/Finschia/finschia-sdk/types"
    46  	sdkerrors "github.com/Finschia/finschia-sdk/types/errors"
    47  )
    48  
    49  // AppModuleBasic is the standard form for basic non-dependant elements of an application module.
    50  type AppModuleBasic interface {
    51  	Name() string
    52  	RegisterLegacyAminoCodec(*codec.LegacyAmino)
    53  	RegisterInterfaces(codectypes.InterfaceRegistry)
    54  
    55  	DefaultGenesis(codec.JSONCodec) json.RawMessage
    56  	ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage) error
    57  
    58  	// client functionality
    59  	RegisterGRPCGatewayRoutes(client.Context, *runtime.ServeMux)
    60  	GetTxCmd() *cobra.Command
    61  	GetQueryCmd() *cobra.Command
    62  }
    63  
    64  // BasicManager is a collection of AppModuleBasic
    65  type BasicManager map[string]AppModuleBasic
    66  
    67  // NewBasicManager creates a new BasicManager object
    68  func NewBasicManager(modules ...AppModuleBasic) BasicManager {
    69  	moduleMap := make(map[string]AppModuleBasic)
    70  	for _, module := range modules {
    71  		moduleMap[module.Name()] = module
    72  	}
    73  	return moduleMap
    74  }
    75  
    76  // RegisterLegacyAminoCodec registers all module codecs
    77  func (bm BasicManager) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
    78  	for _, b := range bm {
    79  		b.RegisterLegacyAminoCodec(cdc)
    80  	}
    81  }
    82  
    83  // RegisterInterfaces registers all module interface types
    84  func (bm BasicManager) RegisterInterfaces(registry codectypes.InterfaceRegistry) {
    85  	for _, m := range bm {
    86  		m.RegisterInterfaces(registry)
    87  	}
    88  }
    89  
    90  // DefaultGenesis provides default genesis information for all modules
    91  func (bm BasicManager) DefaultGenesis(cdc codec.JSONCodec) map[string]json.RawMessage {
    92  	genesis := make(map[string]json.RawMessage)
    93  	for _, b := range bm {
    94  		genesis[b.Name()] = b.DefaultGenesis(cdc)
    95  	}
    96  
    97  	return genesis
    98  }
    99  
   100  // ValidateGenesis performs genesis state validation for all modules
   101  func (bm BasicManager) ValidateGenesis(cdc codec.JSONCodec, txEncCfg client.TxEncodingConfig, genesis map[string]json.RawMessage) error {
   102  	for _, b := range bm {
   103  		if err := b.ValidateGenesis(cdc, txEncCfg, genesis[b.Name()]); err != nil {
   104  			return err
   105  		}
   106  	}
   107  
   108  	return nil
   109  }
   110  
   111  // RegisterGRPCGatewayRoutes registers all module rest routes
   112  func (bm BasicManager) RegisterGRPCGatewayRoutes(clientCtx client.Context, rtr *runtime.ServeMux) {
   113  	for _, b := range bm {
   114  		b.RegisterGRPCGatewayRoutes(clientCtx, rtr)
   115  	}
   116  }
   117  
   118  // AddTxCommands adds all tx commands to the rootTxCmd.
   119  //
   120  // TODO: Remove clientCtx argument.
   121  // REF: https://github.com/cosmos/cosmos-sdk/issues/6571
   122  func (bm BasicManager) AddTxCommands(rootTxCmd *cobra.Command) {
   123  	for _, b := range bm {
   124  		if cmd := b.GetTxCmd(); cmd != nil {
   125  			rootTxCmd.AddCommand(cmd)
   126  		}
   127  	}
   128  }
   129  
   130  // AddQueryCommands adds all query commands to the rootQueryCmd.
   131  //
   132  // TODO: Remove clientCtx argument.
   133  // REF: https://github.com/cosmos/cosmos-sdk/issues/6571
   134  func (bm BasicManager) AddQueryCommands(rootQueryCmd *cobra.Command) {
   135  	for _, b := range bm {
   136  		if cmd := b.GetQueryCmd(); cmd != nil {
   137  			rootQueryCmd.AddCommand(cmd)
   138  		}
   139  	}
   140  }
   141  
   142  // AppModuleGenesis is the standard form for an application module genesis functions
   143  type AppModuleGenesis interface {
   144  	AppModuleBasic
   145  
   146  	InitGenesis(sdk.Context, codec.JSONCodec, json.RawMessage) []abci.ValidatorUpdate
   147  	ExportGenesis(sdk.Context, codec.JSONCodec) json.RawMessage
   148  }
   149  
   150  // AppModule is the standard form for an application module
   151  type AppModule interface {
   152  	AppModuleGenesis
   153  
   154  	// registers
   155  	RegisterInvariants(sdk.InvariantRegistry)
   156  
   157  	// Deprecated: use RegisterServices
   158  	Route() sdk.Route
   159  
   160  	// Deprecated: use RegisterServices
   161  	QuerierRoute() string
   162  
   163  	// Deprecated: use RegisterServices
   164  	LegacyQuerierHandler(*codec.LegacyAmino) sdk.Querier
   165  
   166  	// RegisterServices allows a module to register services
   167  	RegisterServices(Configurator)
   168  
   169  	// ConsensusVersion is a sequence number for state-breaking change of the
   170  	// module. It should be incremented on each consensus-breaking change
   171  	// introduced by the module. To avoid wrong/empty versions, the initial version
   172  	// should be set to 1.
   173  	ConsensusVersion() uint64
   174  }
   175  
   176  // BeginBlockAppModule is an extension interface that contains information about the AppModule and BeginBlock.
   177  type BeginBlockAppModule interface {
   178  	AppModule
   179  	BeginBlock(sdk.Context, ocabci.RequestBeginBlock)
   180  }
   181  
   182  // EndBlockAppModule is an extension interface that contains information about the AppModule and EndBlock.
   183  type EndBlockAppModule interface {
   184  	AppModule
   185  	EndBlock(sdk.Context, abci.RequestEndBlock) []abci.ValidatorUpdate
   186  }
   187  
   188  // GenesisOnlyAppModule is an AppModule that only has import/export functionality
   189  type GenesisOnlyAppModule struct {
   190  	AppModuleGenesis
   191  }
   192  
   193  // NewGenesisOnlyAppModule creates a new GenesisOnlyAppModule object
   194  func NewGenesisOnlyAppModule(amg AppModuleGenesis) AppModule {
   195  	return GenesisOnlyAppModule{
   196  		AppModuleGenesis: amg,
   197  	}
   198  }
   199  
   200  // RegisterInvariants is a placeholder function register no invariants
   201  func (GenesisOnlyAppModule) RegisterInvariants(_ sdk.InvariantRegistry) {}
   202  
   203  // Route empty module message route
   204  func (GenesisOnlyAppModule) Route() sdk.Route { return sdk.Route{} }
   205  
   206  // QuerierRoute returns an empty module querier route
   207  func (GenesisOnlyAppModule) QuerierRoute() string { return "" }
   208  
   209  // LegacyQuerierHandler returns an empty module querier
   210  func (gam GenesisOnlyAppModule) LegacyQuerierHandler(*codec.LegacyAmino) sdk.Querier { return nil }
   211  
   212  // RegisterServices registers all services.
   213  func (gam GenesisOnlyAppModule) RegisterServices(Configurator) {}
   214  
   215  // ConsensusVersion implements AppModule/ConsensusVersion.
   216  func (gam GenesisOnlyAppModule) ConsensusVersion() uint64 { return 1 }
   217  
   218  // BeginBlock returns an empty module begin-block
   219  func (gam GenesisOnlyAppModule) BeginBlock(ctx sdk.Context, req ocabci.RequestBeginBlock) {}
   220  
   221  // EndBlock returns an empty module end-block
   222  func (GenesisOnlyAppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
   223  	return []abci.ValidatorUpdate{}
   224  }
   225  
   226  // Manager defines a module manager that provides the high level utility for managing and executing
   227  // operations for a group of modules
   228  type Manager struct {
   229  	Modules            map[string]AppModule
   230  	OrderInitGenesis   []string
   231  	OrderExportGenesis []string
   232  	OrderBeginBlockers []string
   233  	OrderEndBlockers   []string
   234  	OrderMigrations    []string
   235  }
   236  
   237  // NewManager creates a new Manager object
   238  func NewManager(modules ...AppModule) *Manager {
   239  	moduleMap := make(map[string]AppModule)
   240  	modulesStr := make([]string, 0, len(modules))
   241  	for _, module := range modules {
   242  		moduleMap[module.Name()] = module
   243  		modulesStr = append(modulesStr, module.Name())
   244  	}
   245  
   246  	return &Manager{
   247  		Modules:            moduleMap,
   248  		OrderInitGenesis:   modulesStr,
   249  		OrderExportGenesis: modulesStr,
   250  		OrderBeginBlockers: modulesStr,
   251  		OrderEndBlockers:   modulesStr,
   252  	}
   253  }
   254  
   255  // SetOrderInitGenesis sets the order of init genesis calls
   256  func (m *Manager) SetOrderInitGenesis(moduleNames ...string) {
   257  	m.assertNoForgottenModules("SetOrderInitGenesis", moduleNames)
   258  	m.OrderInitGenesis = moduleNames
   259  }
   260  
   261  // SetOrderExportGenesis sets the order of export genesis calls
   262  func (m *Manager) SetOrderExportGenesis(moduleNames ...string) {
   263  	m.assertNoForgottenModules("SetOrderExportGenesis", moduleNames)
   264  	m.OrderExportGenesis = moduleNames
   265  }
   266  
   267  // SetOrderBeginBlockers sets the order of set begin-blocker calls
   268  func (m *Manager) SetOrderBeginBlockers(moduleNames ...string) {
   269  	m.assertNoForgottenModules("SetOrderBeginBlockers", moduleNames)
   270  	m.OrderBeginBlockers = moduleNames
   271  }
   272  
   273  // SetOrderEndBlockers sets the order of set end-blocker calls
   274  func (m *Manager) SetOrderEndBlockers(moduleNames ...string) {
   275  	m.assertNoForgottenModules("SetOrderEndBlockers", moduleNames)
   276  	m.OrderEndBlockers = moduleNames
   277  }
   278  
   279  // SetOrderMigrations sets the order of migrations to be run. If not set
   280  // then migrations will be run with an order defined in `DefaultMigrationsOrder`.
   281  func (m *Manager) SetOrderMigrations(moduleNames ...string) {
   282  	m.assertNoForgottenModules("SetOrderMigrations", moduleNames)
   283  	m.OrderMigrations = moduleNames
   284  }
   285  
   286  // RegisterInvariants registers all module invariants
   287  func (m *Manager) RegisterInvariants(ir sdk.InvariantRegistry) {
   288  	for _, module := range m.Modules {
   289  		module.RegisterInvariants(ir)
   290  	}
   291  }
   292  
   293  // RegisterRoutes registers all module routes and module querier routes
   294  func (m *Manager) RegisterRoutes(router sdk.Router, queryRouter sdk.QueryRouter, legacyQuerierCdc *codec.LegacyAmino) {
   295  	for _, module := range m.Modules {
   296  		if r := module.Route(); !r.Empty() {
   297  			router.AddRoute(r)
   298  		}
   299  		if r := module.QuerierRoute(); r != "" {
   300  			queryRouter.AddRoute(r, module.LegacyQuerierHandler(legacyQuerierCdc))
   301  		}
   302  	}
   303  }
   304  
   305  // RegisterServices registers all module services
   306  func (m *Manager) RegisterServices(cfg Configurator) {
   307  	for _, module := range m.Modules {
   308  		module.RegisterServices(cfg)
   309  	}
   310  }
   311  
   312  // InitGenesis performs init genesis functionality for modules
   313  func (m *Manager) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, genesisData map[string]json.RawMessage) abci.ResponseInitChain {
   314  	var validatorUpdates []abci.ValidatorUpdate
   315  	for _, moduleName := range m.OrderInitGenesis {
   316  		if genesisData[moduleName] == nil {
   317  			continue
   318  		}
   319  
   320  		moduleValUpdates := m.Modules[moduleName].InitGenesis(ctx, cdc, genesisData[moduleName])
   321  
   322  		// use these validator updates if provided, the module manager assumes
   323  		// only one module will update the validator set
   324  		if len(moduleValUpdates) > 0 {
   325  			if len(validatorUpdates) > 0 {
   326  				panic("validator InitGenesis updates already set by a previous module")
   327  			}
   328  			validatorUpdates = moduleValUpdates
   329  		}
   330  	}
   331  
   332  	return abci.ResponseInitChain{
   333  		Validators: validatorUpdates,
   334  	}
   335  }
   336  
   337  // ExportGenesis performs export genesis functionality for modules
   338  func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) map[string]json.RawMessage {
   339  	genesisData := make(map[string]json.RawMessage)
   340  	for _, moduleName := range m.OrderExportGenesis {
   341  		genesisData[moduleName] = m.Modules[moduleName].ExportGenesis(ctx, cdc)
   342  	}
   343  
   344  	return genesisData
   345  }
   346  
   347  // assertNoForgottenModules checks that we didn't forget any modules in the
   348  // SetOrder* functions.
   349  func (m *Manager) assertNoForgottenModules(setOrderFnName string, moduleNames []string) {
   350  	ms := make(map[string]bool)
   351  	for _, m := range moduleNames {
   352  		ms[m] = true
   353  	}
   354  	var missing []string
   355  	for m := range m.Modules {
   356  		if !ms[m] {
   357  			missing = append(missing, m)
   358  		}
   359  	}
   360  	if len(missing) != 0 {
   361  		panic(fmt.Sprintf(
   362  			"%s: all modules must be defined when setting %s, missing: %v", setOrderFnName, setOrderFnName, missing))
   363  	}
   364  }
   365  
   366  // MigrationHandler is the migration function that each module registers.
   367  type MigrationHandler func(sdk.Context) error
   368  
   369  // VersionMap is a map of moduleName -> version
   370  type VersionMap map[string]uint64
   371  
   372  // RunMigrations performs in-place store migrations for all modules. This
   373  // function MUST be called insde an x/upgrade UpgradeHandler.
   374  //
   375  // Recall that in an upgrade handler, the `fromVM` VersionMap is retrieved from
   376  // x/upgrade's store, and the function needs to return the target VersionMap
   377  // that will in turn be persisted to the x/upgrade's store. In general,
   378  // returning RunMigrations should be enough:
   379  //
   380  // Example:
   381  //
   382  //	cfg := module.NewConfigurator(...)
   383  //	app.UpgradeKeeper.SetUpgradeHandler("my-plan", func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
   384  //	    return app.mm.RunMigrations(ctx, cfg, fromVM)
   385  //	})
   386  //
   387  // Internally, RunMigrations will perform the following steps:
   388  // - create an `updatedVM` VersionMap of module with their latest ConsensusVersion
   389  // - make a diff of `fromVM` and `udpatedVM`, and for each module:
   390  //   - if the module's `fromVM` version is less than its `updatedVM` version,
   391  //     then run in-place store migrations for that module between those versions.
   392  //   - if the module does not exist in the `fromVM` (which means that it's a new module,
   393  //     because it was not in the previous x/upgrade's store), then run
   394  //     `InitGenesis` on that module.
   395  //
   396  // - return the `updatedVM` to be persisted in the x/upgrade's store.
   397  //
   398  // Migrations are run in an order defined by `Manager.OrderMigrations` or (if not set) defined by
   399  // `DefaultMigrationsOrder` function.
   400  //
   401  // As an app developer, if you wish to skip running InitGenesis for your new
   402  // module "foo", you need to manually pass a `fromVM` argument to this function
   403  // foo's module version set to its latest ConsensusVersion. That way, the diff
   404  // between the function's `fromVM` and `udpatedVM` will be empty, hence not
   405  // running anything for foo.
   406  //
   407  // Example:
   408  //
   409  //	cfg := module.NewConfigurator(...)
   410  //	app.UpgradeKeeper.SetUpgradeHandler("my-plan", func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
   411  //	    // Assume "foo" is a new module.
   412  //	    // `fromVM` is fetched from existing x/upgrade store. Since foo didn't exist
   413  //	    // before this upgrade, `v, exists := fromVM["foo"]; exists == false`, and RunMigration will by default
   414  //	    // run InitGenesis on foo.
   415  //	    // To skip running foo's InitGenesis, you need set `fromVM`'s foo to its latest
   416  //	    // consensus version:
   417  //	    fromVM["foo"] = foo.AppModule{}.ConsensusVersion()
   418  //
   419  //	    return app.mm.RunMigrations(ctx, cfg, fromVM)
   420  //	})
   421  //
   422  // Please also refer to docs/core/upgrade.md for more information.
   423  func (m Manager) RunMigrations(ctx sdk.Context, cfg Configurator, fromVM VersionMap) (VersionMap, error) {
   424  	c, ok := cfg.(configurator)
   425  	if !ok {
   426  		return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expected %T, got %T", configurator{}, cfg)
   427  	}
   428  	modules := m.OrderMigrations
   429  	if modules == nil {
   430  		modules = DefaultMigrationsOrder(m.ModuleNames())
   431  	}
   432  
   433  	updatedVM := VersionMap{}
   434  	for _, moduleName := range modules {
   435  		module := m.Modules[moduleName]
   436  		fromVersion, exists := fromVM[moduleName]
   437  		toVersion := module.ConsensusVersion()
   438  
   439  		// Only run migrations when the module exists in the fromVM.
   440  		// Run InitGenesis otherwise.
   441  		//
   442  		// the module won't exist in the fromVM in two cases:
   443  		// 1. A new module is added. In this case we run InitGenesis with an
   444  		// empty genesis state.
   445  		// 2. An existing chain is upgrading to v043 for the first time. In this case,
   446  		// all modules have yet to be added to x/upgrade's VersionMap store.
   447  		if exists {
   448  			err := c.runModuleMigrations(ctx, moduleName, fromVersion, toVersion)
   449  			if err != nil {
   450  				return nil, err
   451  			}
   452  		} else {
   453  			cfgtor, ok := cfg.(configurator)
   454  			if !ok {
   455  				// Currently, the only implementator of Configurator (the interface)
   456  				// is configurator (the struct).
   457  				return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidType, "expected %T, got %T", configurator{}, cfg)
   458  			}
   459  
   460  			moduleValUpdates := module.InitGenesis(ctx, cfgtor.cdc, module.DefaultGenesis(cfgtor.cdc))
   461  			ctx.Logger().Info(fmt.Sprintf("adding a new module: %s", moduleName))
   462  			// The module manager assumes only one module will update the
   463  			// validator set, and that it will not be by a new module.
   464  			if len(moduleValUpdates) > 0 {
   465  				return nil, sdkerrors.Wrapf(sdkerrors.ErrLogic, "validator InitGenesis updates already set by a previous module")
   466  			}
   467  		}
   468  
   469  		updatedVM[moduleName] = toVersion
   470  	}
   471  
   472  	return updatedVM, nil
   473  }
   474  
   475  // BeginBlock performs begin block functionality for all modules. It creates a
   476  // child context with an event manager to aggregate events emitted from all
   477  // modules.
   478  func (m *Manager) BeginBlock(ctx sdk.Context, req ocabci.RequestBeginBlock) abci.ResponseBeginBlock {
   479  	ctx = ctx.WithEventManager(sdk.NewEventManager())
   480  
   481  	for _, moduleName := range m.OrderBeginBlockers {
   482  		module, ok := m.Modules[moduleName].(BeginBlockAppModule)
   483  		if ok {
   484  			module.BeginBlock(ctx, req)
   485  		}
   486  	}
   487  
   488  	return abci.ResponseBeginBlock{
   489  		Events: ctx.EventManager().ABCIEvents(),
   490  	}
   491  }
   492  
   493  // EndBlock performs end block functionality for all modules. It creates a
   494  // child context with an event manager to aggregate events emitted from all
   495  // modules.
   496  func (m *Manager) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
   497  	ctx = ctx.WithEventManager(sdk.NewEventManager())
   498  	validatorUpdates := []abci.ValidatorUpdate{}
   499  
   500  	for _, moduleName := range m.OrderEndBlockers {
   501  		module, ok := m.Modules[moduleName].(EndBlockAppModule)
   502  		if !ok {
   503  			continue
   504  		}
   505  		moduleValUpdates := module.EndBlock(ctx, req)
   506  
   507  		// use these validator updates if provided, the module manager assumes
   508  		// only one module will update the validator set
   509  		if len(moduleValUpdates) > 0 {
   510  			if len(validatorUpdates) > 0 {
   511  				panic("validator EndBlock updates already set by a previous module")
   512  			}
   513  
   514  			validatorUpdates = moduleValUpdates
   515  		}
   516  	}
   517  
   518  	return abci.ResponseEndBlock{
   519  		ValidatorUpdates: validatorUpdates,
   520  		Events:           ctx.EventManager().ABCIEvents(),
   521  	}
   522  }
   523  
   524  // GetVersionMap gets consensus version from all modules
   525  func (m *Manager) GetVersionMap() VersionMap {
   526  	vermap := make(VersionMap)
   527  	for _, v := range m.Modules {
   528  		version := v.ConsensusVersion()
   529  		name := v.Name()
   530  		vermap[name] = version
   531  	}
   532  
   533  	return vermap
   534  }
   535  
   536  // ModuleNames returns list of all module names, without any particular order.
   537  func (m *Manager) ModuleNames() []string {
   538  	ms := make([]string, len(m.Modules))
   539  	i := 0
   540  	for m := range m.Modules {
   541  		ms[i] = m
   542  		i++
   543  	}
   544  	return ms
   545  }
   546  
   547  // DefaultMigrationsOrder returns a default migrations order: ascending alphabetical by module name,
   548  // except x/auth which will run last, see:
   549  // https://github.com/cosmos/cosmos-sdk/issues/10591
   550  func DefaultMigrationsOrder(modules []string) []string {
   551  	const authName = "auth"
   552  	out := make([]string, 0, len(modules))
   553  	hasAuth := false
   554  	for _, m := range modules {
   555  		if m == authName {
   556  			hasAuth = true
   557  		} else {
   558  			out = append(out, m)
   559  		}
   560  	}
   561  	sort.Strings(out)
   562  	if hasAuth {
   563  		out = append(out, authName)
   564  	}
   565  	return out
   566  }