github.com/cosmos/cosmos-sdk@v0.50.10/server/module_hash.go (about) 1 package server 2 3 import ( 4 "encoding/hex" 5 "fmt" 6 "sort" 7 "strconv" 8 "strings" 9 10 "github.com/spf13/cobra" 11 12 "cosmossdk.io/store/rootmulti" 13 storetypes "cosmossdk.io/store/types" 14 15 "github.com/cosmos/cosmos-sdk/client" 16 "github.com/cosmos/cosmos-sdk/client/flags" 17 "github.com/cosmos/cosmos-sdk/server/types" 18 "github.com/cosmos/cosmos-sdk/version" 19 ) 20 21 // ModuleHashByHeightQuery retrieves the module hashes at a given height. 22 func ModuleHashByHeightQuery(appCreator types.AppCreator) *cobra.Command { 23 cmd := &cobra.Command{ 24 Use: "module-hash-by-height [height]", 25 Short: "Get module hashes at a given height", 26 Long: "Get module hashes at a given height. This command is useful for debugging and verifying the state of the application at a given height. Daemon should not be running when calling this command.", 27 Example: fmt.Sprintf("%s module-hash-by-height 16841115", version.AppName), 28 Args: cobra.ExactArgs(1), 29 RunE: func(cmd *cobra.Command, args []string) error { 30 heightToRetrieveString := args[0] 31 32 serverCtx := GetServerContextFromCmd(cmd) 33 34 height, err := strconv.ParseInt(heightToRetrieveString, 10, 64) 35 if err != nil { 36 return fmt.Errorf("invalid height: %w", err) 37 } 38 39 commitInfoForHeight, err := getModuleHashesAtHeight(serverCtx, appCreator, height) 40 if err != nil { 41 return err 42 } 43 44 clientCtx := client.GetClientContextFromCmd(cmd) 45 return clientCtx.PrintProto(commitInfoForHeight) 46 }, 47 } 48 49 flags.AddQueryFlagsToCmd(cmd) 50 51 return cmd 52 } 53 54 func getModuleHashesAtHeight(svrCtx *Context, appCreator types.AppCreator, height int64) (*storetypes.CommitInfo, error) { 55 home := svrCtx.Config.RootDir 56 db, err := openDB(home, GetAppDBBackend(svrCtx.Viper)) 57 if err != nil { 58 return nil, fmt.Errorf("error opening DB, make sure daemon is not running when calling this query: %w", err) 59 } 60 app := appCreator(svrCtx.Logger, db, nil, svrCtx.Viper) 61 rms, ok := app.CommitMultiStore().(*rootmulti.Store) 62 if !ok { 63 return nil, fmt.Errorf("expected rootmulti.Store, got %T", app.CommitMultiStore()) 64 } 65 66 commitInfoForHeight, err := rms.GetCommitInfo(height) 67 if err != nil { 68 return nil, err 69 } 70 71 // Create a new slice of StoreInfos for storing the modified hashes. 72 storeInfos := make([]storetypes.StoreInfo, len(commitInfoForHeight.StoreInfos)) 73 74 for i, storeInfo := range commitInfoForHeight.StoreInfos { 75 // Convert the hash to a hexadecimal string. 76 hash := strings.ToUpper(hex.EncodeToString(storeInfo.CommitId.Hash)) 77 78 // Create a new StoreInfo with the modified hash. 79 storeInfos[i] = storetypes.StoreInfo{ 80 Name: storeInfo.Name, 81 CommitId: storetypes.CommitID{ 82 Version: storeInfo.CommitId.Version, 83 Hash: []byte(hash), 84 }, 85 } 86 } 87 88 // Sort the storeInfos slice based on the module name. 89 sort.Slice(storeInfos, func(i, j int) bool { 90 return storeInfos[i].Name < storeInfos[j].Name 91 }) 92 93 // Create a new CommitInfo with the modified StoreInfos. 94 commitInfoForHeight = &storetypes.CommitInfo{ 95 Version: commitInfoForHeight.Version, 96 StoreInfos: storeInfos, 97 Timestamp: commitInfoForHeight.Timestamp, 98 } 99 100 return commitInfoForHeight, nil 101 }