github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/cmd/fbchaind/iaviewer.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/sha256"
     6  	"encoding/binary"
     7  	"encoding/hex"
     8  	"encoding/json"
     9  	"fmt"
    10  	"os"
    11  	"sort"
    12  	"strconv"
    13  	"strings"
    14  	"sync"
    15  
    16  	ethcmn "github.com/ethereum/go-ethereum/common"
    17  	ethtypes "github.com/ethereum/go-ethereum/core/types"
    18  	"github.com/gogo/protobuf/proto"
    19  
    20  	"github.com/fibonacci-chain/fbc/app"
    21  	"github.com/fibonacci-chain/fbc/cmd/fbchaind/base"
    22  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec"
    23  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/server"
    24  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    25  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/exported"
    26  	acctypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/types"
    27  	distypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/distribution/types"
    28  	govtypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/gov/types"
    29  	minttypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/mint"
    30  	stakingtypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/staking/types"
    31  	supplytypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/supply"
    32  	"github.com/fibonacci-chain/fbc/libs/iavl"
    33  	abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types"
    34  	"github.com/fibonacci-chain/fbc/libs/tendermint/crypto"
    35  	tmtypes "github.com/fibonacci-chain/fbc/libs/tendermint/types"
    36  	dbm "github.com/fibonacci-chain/fbc/libs/tm-db"
    37  	"github.com/fibonacci-chain/fbc/x/distribution/types"
    38  	evmtypes "github.com/fibonacci-chain/fbc/x/evm/types"
    39  	"github.com/fibonacci-chain/fbc/x/gov"
    40  	slashingtypes "github.com/fibonacci-chain/fbc/x/slashing"
    41  	tokentypes "github.com/fibonacci-chain/fbc/x/token/types"
    42  
    43  	"github.com/spf13/cobra"
    44  	"github.com/spf13/viper"
    45  )
    46  
    47  type (
    48  	formatKeyValue func(cdc *codec.Codec, key []byte, value []byte) string
    49  )
    50  
    51  const (
    52  	KeyDistribution = "s/k:distribution/"
    53  	KeyGov          = "s/k:gov/"
    54  	KeyMain         = "s/k:main/"
    55  	KeyToken        = "s/k:token/"
    56  	KeyMint         = "s/k:mint/"
    57  	KeyAcc          = "s/k:acc/"
    58  	KeySupply       = "s/k:supply/"
    59  	KeyEvm          = "s/k:evm/"
    60  	KeyEvmLegacy    = "s/k:evmlegacy/"
    61  	KeyParams       = "s/k:params/"
    62  	KeyStaking      = "s/k:staking/"
    63  	KeySlashing     = "s/k:slashing/"
    64  
    65  	DefaultCacheSize int = 100000
    66  
    67  	flagStart            = "start"
    68  	flagLimit            = "limit"
    69  	flagHex              = "hex"
    70  	flagPrefix           = "prefix"
    71  	flagKey              = "key"
    72  	flagNodeHash         = "nodehash"
    73  	flagKeyPrefix        = "keyprefix"
    74  	flagNodePrefix       = "node-prefix"
    75  	flagNodePrefixFormat = "node-prefix-format"
    76  	flagCount            = "count"
    77  )
    78  
    79  var printKeysDict = map[string]formatKeyValue{
    80  	KeyEvm:          evmPrintKey,
    81  	KeyEvmLegacy:    evmPrintKey,
    82  	KeyAcc:          accPrintKey,
    83  	KeyParams:       paramsPrintKey,
    84  	KeyStaking:      stakingPrintKey,
    85  	KeyGov:          govPrintKey,
    86  	KeyDistribution: distributionPrintKey,
    87  	KeySlashing:     slashingPrintKey,
    88  	KeyMain:         mainPrintKey,
    89  	KeyToken:        tokenPrintKey,
    90  	KeyMint:         mintPrintKey,
    91  	KeySupply:       supplyPrintKey,
    92  }
    93  
    94  type iaviewerFlags struct {
    95  	Start     *int
    96  	Limit     *int
    97  	DbBackend *string
    98  	Prefix    *string
    99  }
   100  
   101  type iaviewerContext struct {
   102  	DataDir   string
   103  	Prefix    string
   104  	Module    string
   105  	Version   int
   106  	DbBackend dbm.BackendType
   107  	Start     int
   108  	Limit     int
   109  	Codec     *codec.Codec
   110  
   111  	flags          iaviewerFlags
   112  	noParseVersion bool
   113  	extra          map[string]interface{}
   114  }
   115  
   116  func iaviewerCmd(ctx *server.Context, cdc *codec.Codec) *cobra.Command {
   117  	cmd := &cobra.Command{
   118  		Use:   "iaviewer",
   119  		Short: "Read iavl tree data from db",
   120  		PersistentPreRun: func(cmd *cobra.Command, args []string) {
   121  			iavl.SetEnableFastStorage(false)
   122  			viper.Set(iavl.FlagIavlEnableFastStorage, false)
   123  		},
   124  	}
   125  	iavlCtx := &iaviewerContext{Codec: cdc, DbBackend: dbm.BackendType(ctx.Config.DBBackend), extra: map[string]interface{}{}}
   126  
   127  	cmd.AddCommand(
   128  		iaviewerReadCmd(iavlCtx),
   129  		iaviewerReadNodeCmd(iavlCtx),
   130  		iaviewerDBNodeCmd(iavlCtx),
   131  		iaviewerStatusCmd(iavlCtx),
   132  		iaviewerDiffCmd(iavlCtx),
   133  		iaviewerVersionsCmd(iavlCtx),
   134  		iaviewerListModulesCmd(),
   135  	)
   136  	iavlCtx.flags.DbBackend = cmd.PersistentFlags().String(sdk.FlagDBBackend, tmtypes.DBBackend, "Database backend: goleveldb | rocksdb")
   137  	iavlCtx.flags.Start = cmd.PersistentFlags().Int(flagStart, 0, "index of result set start from")
   138  	iavlCtx.flags.Limit = cmd.PersistentFlags().Int(flagLimit, 0, "limit of result set, 0 means no limit")
   139  	iavlCtx.flags.Prefix = cmd.PersistentFlags().String(flagPrefix, "", "the prefix of iavl tree, module value must be \"\" if prefix is set")
   140  	return cmd
   141  }
   142  
   143  func iaviewerCmdParseFlags(ctx *iaviewerContext) {
   144  	if dbflag := ctx.flags.DbBackend; dbflag != nil && *dbflag != "" {
   145  		ctx.DbBackend = dbm.BackendType(*dbflag)
   146  	}
   147  
   148  	if ctx.flags.Start != nil {
   149  		ctx.Start = *ctx.flags.Start
   150  	}
   151  	if ctx.flags.Limit != nil {
   152  		ctx.Limit = *ctx.flags.Limit
   153  	}
   154  
   155  	if ctx.flags.Prefix != nil && *ctx.flags.Prefix != "" {
   156  		ctx.Prefix = *ctx.flags.Prefix
   157  	}
   158  }
   159  
   160  func iaviewerCmdParseArgs(ctx *iaviewerContext, args []string) (err error) {
   161  	if len(args) < 2 {
   162  		return fmt.Errorf("must specify data_dir and module")
   163  	}
   164  	dataDir, module, version := args[0], args[1], 0
   165  	if !ctx.noParseVersion && len(args) == 3 {
   166  		version, err = strconv.Atoi(args[2])
   167  		if err != nil {
   168  			return fmt.Errorf("invalid version: %s, error : %w\n", args[2], err)
   169  		}
   170  	}
   171  	ctx.DataDir = dataDir
   172  	ctx.Module = module
   173  	ctx.Version = version
   174  	if ctx.Module != "" {
   175  		ctx.Prefix = fmt.Sprintf("s/k:%s/", ctx.Module)
   176  	}
   177  	return nil
   178  }
   179  
   180  func iaviewerListModulesCmd() *cobra.Command {
   181  	cmd := &cobra.Command{
   182  		Use:   "list-modules",
   183  		Short: "List all module names",
   184  		Run: func(cmd *cobra.Command, args []string) {
   185  			moduleKeys := make([]string, 0, len(app.ModuleBasics))
   186  			for moduleKey := range app.ModuleBasics {
   187  				moduleKeys = append(moduleKeys, moduleKey)
   188  			}
   189  			sort.Strings(moduleKeys)
   190  			fmt.Printf("there are %d modules:\n\n", len(moduleKeys))
   191  			for _, key := range moduleKeys {
   192  				fmt.Print("\t")
   193  				fmt.Println(key)
   194  			}
   195  			fmt.Println()
   196  		},
   197  	}
   198  	return cmd
   199  }
   200  
   201  func iaviewerReadCmd(ctx *iaviewerContext) *cobra.Command {
   202  	cmd := &cobra.Command{
   203  		Use:   "read <data_dir> <module> [version]",
   204  		Short: "Read iavl tree key-value from db",
   205  		Long:  "Read iavl tree key-value from db, you must specify data_dir and module, if version is 0 or not specified, read data from the latest version.\n",
   206  		PreRunE: func(cmd *cobra.Command, args []string) (err error) {
   207  			iaviewerCmdParseFlags(ctx)
   208  			return iaviewerCmdParseArgs(ctx, args)
   209  		},
   210  		RunE: func(cmd *cobra.Command, args []string) (err error) {
   211  			return iaviewerReadData(ctx)
   212  		},
   213  	}
   214  	cmd.PersistentFlags().Bool(flagHex, false, "print key and value in hex format")
   215  	cmd.PersistentFlags().String(flagKey, "", "print only the value for this key, key must be in hex format.\n"+
   216  		"if specified, keyprefix, start and limit flags would be ignored")
   217  	cmd.PersistentFlags().String(flagKeyPrefix, "", "print values for keys with specified prefix, prefix must be in hex format.")
   218  	return cmd
   219  }
   220  
   221  func iaviewerReadNodeCmd(ctx *iaviewerContext) *cobra.Command {
   222  	cmd := &cobra.Command{
   223  		Use:   "read-node <data_dir> <module> [version]",
   224  		Short: "Read iavl tree node from db",
   225  		Long:  "Read iavl tree node from db, you must specify data_dir and module, if version is 0 or not specified, read data from the latest version.\n",
   226  		PreRunE: func(cmd *cobra.Command, args []string) (err error) {
   227  			iaviewerCmdParseFlags(ctx)
   228  			return iaviewerCmdParseArgs(ctx, args)
   229  		},
   230  		RunE: func(cmd *cobra.Command, args []string) (err error) {
   231  			return iaviewerReadNodeData(ctx)
   232  		},
   233  	}
   234  	cmd.PersistentFlags().String(flagNodeHash, "", "print only the value for this hash, key must be in hex format.")
   235  	return cmd
   236  }
   237  
   238  func iaviewerDBNodeCmd(ctx *iaviewerContext) *cobra.Command {
   239  	cmd := &cobra.Command{
   240  		Use:   "db-node <data_dir> <module>",
   241  		Short: "read iavl tree node from db direct",
   242  		PreRunE: func(cmd *cobra.Command, args []string) (err error) {
   243  			ctx.noParseVersion = true
   244  			iaviewerCmdParseFlags(ctx)
   245  			return iaviewerCmdParseArgs(ctx, args)
   246  		},
   247  		RunE: func(cmd *cobra.Command, args []string) (err error) {
   248  			return iaviewerDBNodeData(ctx)
   249  		},
   250  	}
   251  	ctx.extra[flagNodePrefix] = cmd.PersistentFlags().String(flagNodePrefix, "r", "node prefix, (r, n, o, f, m, ...)")
   252  	ctx.extra[flagNodePrefixFormat] = cmd.PersistentFlags().String(flagNodePrefixFormat, "a", "a: nodePrefix in ascii, h: nodePrefix in hex")
   253  	ctx.extra[flagCount] = cmd.PersistentFlags().Bool(flagCount, true, "only count node number, do not print node data")
   254  	return cmd
   255  }
   256  
   257  func iaviewerStatusCmd(ctx *iaviewerContext) *cobra.Command {
   258  	cmd := &cobra.Command{
   259  		Use:   "status <data_dir> <module> [version]",
   260  		Short: "print iavl tree status",
   261  		Long:  "print iavl tree status, you must specify data_dir and module, if version is 0 or not specified, read data from the latest version.\n",
   262  		PreRunE: func(cmd *cobra.Command, args []string) (err error) {
   263  			iaviewerCmdParseFlags(ctx)
   264  			return iaviewerCmdParseArgs(ctx, args)
   265  		},
   266  		RunE: func(cmd *cobra.Command, args []string) (err error) {
   267  			return iaviewerStatus(ctx)
   268  		},
   269  	}
   270  	return cmd
   271  }
   272  
   273  func iaviewerVersionsCmd(ctx *iaviewerContext) *cobra.Command {
   274  	cmd := &cobra.Command{
   275  		Use:   "versions <data_dir> <module> [version]",
   276  		Short: "list iavl tree versions",
   277  		PreRunE: func(cmd *cobra.Command, args []string) (err error) {
   278  			iaviewerCmdParseFlags(ctx)
   279  			return iaviewerCmdParseArgs(ctx, args)
   280  		},
   281  		RunE: func(cmd *cobra.Command, args []string) (err error) {
   282  			return iaviewerVersions(ctx)
   283  		},
   284  	}
   285  	return cmd
   286  }
   287  
   288  func iaviewerDiffCmd(ctx *iaviewerContext) *cobra.Command {
   289  	var ver2 int
   290  	cmd := &cobra.Command{
   291  		Use:   "diff <data_dir> <module> <version1> <version2>",
   292  		Short: "compare different key-value between two versions",
   293  		PreRunE: func(cmd *cobra.Command, args []string) error {
   294  			iaviewerCmdParseFlags(ctx)
   295  			if len(args) != 4 {
   296  				return fmt.Errorf("must specify data_dir, module, version1 and version2")
   297  			}
   298  			ctx.DataDir = args[0]
   299  			ctx.Module = args[1]
   300  			if ctx.Module != "" {
   301  				ctx.Prefix = fmt.Sprintf("s/k:%s/", ctx.Module)
   302  			}
   303  
   304  			ver1, err := strconv.Atoi(args[2])
   305  			if err != nil {
   306  				return fmt.Errorf("invalid version1: %s, error : %w\n", args[2], err)
   307  			}
   308  			ctx.Version = ver1
   309  			ver2, err = strconv.Atoi(args[3])
   310  			if err != nil {
   311  				return fmt.Errorf("invalid version2: %s, error : %w\n", args[3], err)
   312  			}
   313  			return nil
   314  		},
   315  		RunE: func(cmd *cobra.Command, args []string) error {
   316  			return iaviewerPrintDiff(ctx, ver2)
   317  		},
   318  	}
   319  	cmd.PersistentFlags().Bool(flagHex, false, "print key and value in hex format")
   320  	cmd.PersistentFlags().String(flagKeyPrefix, "", "diff values for keys with specified prefix, prefix must be in hex format.")
   321  	return cmd
   322  }
   323  
   324  // iaviewerPrintDiff reads different key-value from leveldb according two paths
   325  func iaviewerPrintDiff(ctx *iaviewerContext, version2 int) error {
   326  	db, err := base.OpenDB(ctx.DataDir, ctx.DbBackend)
   327  	if err != nil {
   328  		return fmt.Errorf("error opening DB: %w", err)
   329  	}
   330  	defer db.Close()
   331  
   332  	tree, err := ReadTree(db, ctx.Version, []byte(ctx.Prefix), DefaultCacheSize*100)
   333  	if err != nil {
   334  		return fmt.Errorf("error reading data: %w", err)
   335  	}
   336  	compareTree, err := ReadTree(db, version2, []byte(ctx.Prefix), DefaultCacheSize*100)
   337  	if err != nil {
   338  		return fmt.Errorf("error reading data: %w", err)
   339  	}
   340  	fmt.Printf("module: %s, prefix key: %s\n\n", ctx.Module, ctx.Prefix)
   341  
   342  	if bytes.Equal(tree.Hash(), compareTree.Hash()) {
   343  		fmt.Printf("tree version %d and %d are same, root hash: %X\n", ctx.Version, version2, tree.Hash())
   344  		return nil
   345  	}
   346  
   347  	var startKey, endKey []byte
   348  	if keyPrefixStr := viper.GetString(flagKeyPrefix); keyPrefixStr != "" {
   349  		startKey, err = hex.DecodeString(keyPrefixStr)
   350  		if err != nil {
   351  			return fmt.Errorf("invalid key prefix: %s, error: %w", keyPrefixStr, err)
   352  		}
   353  		endKey = calcEndKey(startKey)
   354  	}
   355  
   356  	wg := &sync.WaitGroup{}
   357  	wg.Add(2)
   358  
   359  	go func(wg *sync.WaitGroup) {
   360  		tree.IterateRange(startKey, endKey, true, func(key, value []byte) bool {
   361  			_, v2 := compareTree.GetWithIndex(key)
   362  			if v2 == nil {
   363  				fmt.Printf("---only in ver1 %d, %s\n", ctx.Version, formatKV(ctx.Codec, ctx.Prefix, key, value))
   364  			} else {
   365  				if !bytes.Equal(value, v2) {
   366  					fmt.Printf("---diff ver1 %d, %s\n", ctx.Version, formatKV(ctx.Codec, ctx.Prefix, key, value))
   367  					fmt.Printf("+++diff ver2 %d, %s\n", version2, formatKV(ctx.Codec, ctx.Prefix, key, v2))
   368  				}
   369  			}
   370  			return false
   371  		})
   372  		wg.Done()
   373  	}(wg)
   374  
   375  	go func(wg *sync.WaitGroup) {
   376  		compareTree.IterateRange(startKey, endKey, true, func(key, value []byte) bool {
   377  			_, v1 := tree.GetWithIndex(key)
   378  			if v1 == nil {
   379  				fmt.Printf("+++only in ver2 %d, %s\n", version2, formatKV(ctx.Codec, ctx.Prefix, key, value))
   380  			}
   381  			return false
   382  		})
   383  		wg.Done()
   384  	}(wg)
   385  
   386  	wg.Wait()
   387  
   388  	return nil
   389  }
   390  
   391  // iaviewerReadData reads key-value from leveldb
   392  func iaviewerReadData(ctx *iaviewerContext) error {
   393  	db, err := base.OpenDB(ctx.DataDir, ctx.DbBackend)
   394  	if err != nil {
   395  		return fmt.Errorf("error opening DB: %w", err)
   396  	}
   397  	defer db.Close()
   398  
   399  	tree, err := ReadTree(db, ctx.Version, []byte(ctx.Prefix), DefaultCacheSize)
   400  	if err != nil {
   401  		return fmt.Errorf("error reading data: %w", err)
   402  	}
   403  	fmt.Printf("module: %s, prefix key: %s\n\n", ctx.Module, ctx.Prefix)
   404  
   405  	if key := viper.GetString(flagKey); key != "" {
   406  		keyByte, err := hex.DecodeString(key)
   407  		if err != nil {
   408  			return fmt.Errorf("error decoding key: %w", err)
   409  		}
   410  		i, value := tree.GetWithIndex(keyByte)
   411  
   412  		if impl, exit := printKeysDict[ctx.Prefix]; exit && !viper.GetBool(flagHex) {
   413  			kvFormat := impl(ctx.Codec, keyByte, value)
   414  			if kvFormat != "" {
   415  				fmt.Println(kvFormat)
   416  				fmt.Println()
   417  			}
   418  		}
   419  
   420  		fmt.Printf("key:\t%s\nvalue:\t%X\nindex:\t%d\n", key, value, i)
   421  		return nil
   422  	}
   423  
   424  	printTree(ctx, tree)
   425  	return nil
   426  }
   427  
   428  func iaviewerReadNodeData(ctx *iaviewerContext) error {
   429  	db, err := base.OpenDB(ctx.DataDir, ctx.DbBackend)
   430  	if err != nil {
   431  		return fmt.Errorf("error opening DB: %w", err)
   432  	}
   433  	defer db.Close()
   434  
   435  	tree, err := ReadTree(db, ctx.Version, []byte(ctx.Prefix), DefaultCacheSize)
   436  	if err != nil {
   437  		return fmt.Errorf("error reading data: %w", err)
   438  	}
   439  	fmt.Printf("module: %s, prefix key: %s\n\n", ctx.Module, ctx.Prefix)
   440  
   441  	var nodeHash []byte
   442  	if key := viper.GetString(flagNodeHash); key != "" {
   443  		nodeHash, err = hex.DecodeString(key)
   444  		if err != nil {
   445  			return fmt.Errorf("error decoding key: %w", err)
   446  		}
   447  		if len(nodeHash) != 32 {
   448  			return fmt.Errorf("invalid node hash: %s", key)
   449  		}
   450  
   451  	} else {
   452  		nodeHash = tree.Hash()
   453  	}
   454  
   455  	node := tree.DebugGetNode(nodeHash)
   456  	if node == nil {
   457  		return fmt.Errorf("node not found: %s", nodeHash)
   458  	}
   459  
   460  	jstr, err := json.Marshal(newNodeStringFromNodeJson(iavl.NodeToNodeJson(node)))
   461  	if err != nil {
   462  		fmt.Println(node.String())
   463  	} else {
   464  		fmt.Println(string(jstr))
   465  	}
   466  
   467  	return nil
   468  }
   469  
   470  func iaviewerDBNodeData(ctx *iaviewerContext) error {
   471  	db, err := base.OpenDB(ctx.DataDir, ctx.DbBackend)
   472  	if err != nil {
   473  		return fmt.Errorf("error opening DB: %w", err)
   474  	}
   475  	defer db.Close()
   476  
   477  	pdb := dbm.NewPrefixDB(db, []byte(ctx.Prefix))
   478  
   479  	nodePrefixFormat := strings.ToLower(*ctx.extra[flagNodePrefixFormat].(*string))
   480  
   481  	nodePrefix := *ctx.extra[flagNodePrefix].(*string)
   482  	start := []byte(nodePrefix)
   483  	switch nodePrefixFormat {
   484  	case "hex":
   485  		fallthrough
   486  	case "h":
   487  		start, err = hex.DecodeString(nodePrefix)
   488  		if err != nil {
   489  			return fmt.Errorf("error decoding node prefix: %w", err)
   490  		}
   491  	}
   492  	end := calcEndKey(start)
   493  	iter, err := pdb.Iterator(start, end)
   494  	if err != nil {
   495  		return fmt.Errorf("error opening iterator: %w", err)
   496  	}
   497  	defer iter.Close()
   498  
   499  	onlyCount := *ctx.extra[flagCount].(*bool)
   500  	count := 0
   501  	index := 0
   502  
   503  	if onlyCount {
   504  		for ; iter.Valid(); iter.Next() {
   505  			if ctx.Start > index {
   506  				continue
   507  			}
   508  			count++
   509  			if ctx.Limit != 0 && ctx.Limit < count {
   510  				break
   511  			}
   512  		}
   513  	} else {
   514  		for ; iter.Valid(); iter.Next() {
   515  			if ctx.Start > index {
   516  				continue
   517  			}
   518  			count++
   519  			if ctx.Limit != 0 && ctx.Limit < count {
   520  				break
   521  			}
   522  			key := iter.Key()
   523  			value := iter.Value()
   524  			fmt.Printf("key:%s, value:%s\n", hex.EncodeToString(key), hex.EncodeToString(value))
   525  		}
   526  	}
   527  	fmt.Printf("count : %d\n", count)
   528  
   529  	return nil
   530  }
   531  
   532  type nodeString struct {
   533  	Key          string `json:"key"`
   534  	Value        string `json:"value"`
   535  	Hash         string `json:"hash"`
   536  	LeftHash     string `json:"left_hash"`
   537  	RightHash    string `json:"right_hash"`
   538  	Version      int64  `json:"version"`
   539  	Size         int64  `json:"size"`
   540  	Height       int8   `json:"height"`
   541  	Persisted    bool   `json:"persisted"`
   542  	PrePersisted bool   `json:"pre_persisted"`
   543  }
   544  
   545  func newNodeStringFromNodeJson(nodeJson *iavl.NodeJson) *nodeString {
   546  	return &nodeString{
   547  		Key:          hex.EncodeToString(nodeJson.Key),
   548  		Value:        hex.EncodeToString(nodeJson.Value),
   549  		Hash:         hex.EncodeToString(nodeJson.Hash),
   550  		LeftHash:     hex.EncodeToString(nodeJson.LeftHash),
   551  		RightHash:    hex.EncodeToString(nodeJson.RightHash),
   552  		Version:      nodeJson.Version,
   553  		Size:         nodeJson.Size,
   554  		Height:       nodeJson.Height,
   555  		Persisted:    nodeJson.Persisted,
   556  		PrePersisted: nodeJson.PrePersisted,
   557  	}
   558  }
   559  
   560  func iaviewerStatus(ctx *iaviewerContext) error {
   561  	db, err := base.OpenDB(ctx.DataDir, ctx.DbBackend)
   562  	if err != nil {
   563  		return fmt.Errorf("error opening DB: %w", err)
   564  	}
   565  	defer db.Close()
   566  
   567  	tree, err := ReadTree(db, ctx.Version, []byte(ctx.Prefix), DefaultCacheSize)
   568  	if err != nil {
   569  		return fmt.Errorf("error reading data: %w", err)
   570  	}
   571  	fmt.Printf("module: %s, prefix key: %s\n", ctx.Module, ctx.Prefix)
   572  	printIaviewerStatus(tree)
   573  	return nil
   574  }
   575  
   576  func printIaviewerStatus(tree *iavl.MutableTree) {
   577  	fmt.Printf("iavl tree:\n"+
   578  		"\troot hash: %X\n"+
   579  		"\tsize: %d\n"+
   580  		"\tcurrent version: %d\n"+
   581  		"\theight: %d\n", tree.Hash(), tree.Size(), tree.Version(), tree.Height())
   582  
   583  	fss, err := tree.DebugFssVersion()
   584  	if err != nil {
   585  		fmt.Printf("fss version error %w\n", err)
   586  	} else {
   587  		fmt.Printf("fss version: %s\n", string(fss))
   588  	}
   589  }
   590  
   591  func iaviewerVersions(ctx *iaviewerContext) error {
   592  	db, err := base.OpenDB(ctx.DataDir, ctx.DbBackend)
   593  	if err != nil {
   594  		return fmt.Errorf("error opening DB: %w", err)
   595  	}
   596  	defer db.Close()
   597  
   598  	tree, err := ReadTree(db, ctx.Version, []byte(ctx.Prefix), DefaultCacheSize)
   599  	if err != nil {
   600  		return fmt.Errorf("error reading data: %w", err)
   601  	}
   602  	fmt.Printf("module: %s, prefix key: %s\n\n", ctx.Module, ctx.Prefix)
   603  	iaviewerPrintVersions(ctx, tree)
   604  	return nil
   605  }
   606  
   607  func iaviewerPrintVersions(ctx *iaviewerContext, tree *iavl.MutableTree) {
   608  	versions := tree.AvailableVersions()
   609  	fmt.Printf("total versions: %d\n", len(versions))
   610  
   611  	if ctx.Start >= len(versions) {
   612  		fmt.Printf("printed verions: 0\n")
   613  		return
   614  	}
   615  	if ctx.Start+ctx.Limit > len(versions) {
   616  		ctx.Limit = len(versions) - ctx.Start
   617  	}
   618  	if ctx.Limit == 0 {
   619  		versions = versions[ctx.Start:]
   620  	} else {
   621  		versions = versions[ctx.Start : ctx.Start+ctx.Limit]
   622  	}
   623  	fmt.Printf("printed versions: %d\n\n", len(versions))
   624  
   625  	for _, v := range versions {
   626  		fmt.Printf("  %d\n", v)
   627  	}
   628  }
   629  
   630  // getKVs, get all key-values by mutableTree
   631  func getKVs(tree *iavl.MutableTree, dataMap map[string][32]byte, wg *sync.WaitGroup) {
   632  	tree.Iterate(func(key []byte, value []byte) bool {
   633  		dataMap[hex.EncodeToString(key)] = sha256.Sum256(value)
   634  		return false
   635  	})
   636  	wg.Done()
   637  }
   638  
   639  func defaultKvFormatter(key []byte, value []byte) string {
   640  	printKey := parseWeaveKey(key)
   641  	return fmt.Sprintf("parsed key:\t%s\nhex key:\t%X\nhex value:\t%X", printKey, key, value)
   642  }
   643  
   644  func formatKV(cdc *codec.Codec, modulePrefixKey string, key []byte, value []byte) string {
   645  	if impl, exit := printKeysDict[modulePrefixKey]; exit && !viper.GetBool(flagHex) {
   646  		kvFormat := impl(cdc, key, value)
   647  		if kvFormat != "" {
   648  			return kvFormat
   649  		}
   650  	}
   651  	return defaultKvFormatter(key, value)
   652  }
   653  
   654  func printKV(cdc *codec.Codec, modulePrefixKey string, key []byte, value []byte) {
   655  	fmt.Println(formatKV(cdc, modulePrefixKey, key, value))
   656  	fmt.Println()
   657  }
   658  
   659  func calcEndKey(key []byte) []byte {
   660  	if len(key) == 0 {
   661  		return nil
   662  	}
   663  	endKey := make([]byte, len(key))
   664  	copy(endKey, key)
   665  	last := len(endKey) - 1
   666  	endKey[last]++
   667  	for endKey[last] == 0 {
   668  		if last == 0 {
   669  			return nil
   670  		}
   671  		last--
   672  		endKey[last]++
   673  	}
   674  	return endKey[0 : last+1]
   675  }
   676  
   677  func printTree(ctx *iaviewerContext, tree *iavl.MutableTree) {
   678  	startKey := []byte(nil)
   679  	endKey := []byte(nil)
   680  
   681  	var keyPrefix []byte
   682  	var err error
   683  	var total = tree.Size()
   684  	if keyPrefixStr := viper.GetString(flagKeyPrefix); keyPrefixStr != "" {
   685  		keyPrefix, err = hex.DecodeString(keyPrefixStr)
   686  		if err != nil {
   687  			fmt.Printf("keyprefix must be in hex format: %s\n", err)
   688  			os.Exit(1)
   689  		}
   690  		index, _ := tree.GetWithIndex(keyPrefix)
   691  		ctx.Start += int(index)
   692  		endKey = calcEndKey(keyPrefix)
   693  		index2, _ := tree.GetWithIndex(endKey)
   694  		total = index2 - index
   695  		limit := int(total)
   696  		if ctx.Limit == 0 || limit < ctx.Limit {
   697  			ctx.Limit = limit
   698  		}
   699  	}
   700  
   701  	if tree.Size() <= int64(ctx.Start) {
   702  		return
   703  	}
   704  	printed := ctx.Limit
   705  	if ctx.Start != 0 {
   706  		startKey, _ = tree.GetByIndex(int64(ctx.Start))
   707  	}
   708  	if ctx.Limit != 0 && int64(ctx.Start+ctx.Limit) < tree.Size() {
   709  		endKey, _ = tree.GetByIndex(int64(ctx.Start + ctx.Limit))
   710  	} else {
   711  		printed = int(tree.Size()) - ctx.Start
   712  	}
   713  
   714  	fmt.Printf("total: %d\n", total)
   715  	fmt.Printf("printed: %d\n\n", printed)
   716  
   717  	tree.IterateRange(startKey, endKey, true, func(key []byte, value []byte) bool {
   718  		if len(keyPrefix) != 0 {
   719  			if !bytes.HasPrefix(key, keyPrefix) {
   720  				return true
   721  			}
   722  		}
   723  		printKV(ctx.Codec, ctx.Prefix, key, value)
   724  		return false
   725  	})
   726  
   727  	//tree.Iterate(func(key []byte, value []byte) bool {
   728  	//	printKV(ctx.Codec, ctx.Prefix, key, value)
   729  	//	return false
   730  	//})
   731  }
   732  
   733  func printByKey(cdc *codec.Codec, tree *iavl.MutableTree, module string, key []byte) {
   734  	_, value := tree.GetWithIndex(key)
   735  	printKV(cdc, module, key, value)
   736  }
   737  
   738  func supplyPrintKey(cdc *codec.Codec, key []byte, value []byte) string {
   739  	switch key[0] {
   740  	case supplytypes.SupplyKey[0]:
   741  		var supplyAmount sdk.Dec
   742  		cdc.MustUnmarshalBinaryLengthPrefixed(value, &supplyAmount)
   743  		return fmt.Sprintf("tokenSymbol:%s:info:%s", string(key[1:]), supplyAmount.String())
   744  	default:
   745  		return defaultKvFormatter(key, value)
   746  	}
   747  }
   748  
   749  type MinterCustom struct {
   750  	NextBlockToUpdate uint64       `json:"next_block_to_update" yaml:"next_block_to_update"` // record the block height for next year
   751  	MintedPerBlock    sdk.DecCoins `json:"minted_per_block" yaml:"minted_per_block"`         // record the MintedPerBlock per block in this year
   752  }
   753  
   754  func mintPrintKey(cdc *codec.Codec, key []byte, value []byte) string {
   755  	switch key[0] {
   756  	case minttypes.MinterKey[0]:
   757  		var minter MinterCustom
   758  		cdc.MustUnmarshalBinaryLengthPrefixed(value, &minter)
   759  		return fmt.Sprintf("minter:%v", minter)
   760  	default:
   761  		return defaultKvFormatter(key, value)
   762  	}
   763  }
   764  
   765  func tokenPrintKey(cdc *codec.Codec, key []byte, value []byte) string {
   766  	switch key[0] {
   767  	case tokentypes.TokenKey[0]:
   768  		var token tokentypes.Token
   769  		cdc.MustUnmarshalBinaryBare(value, &token)
   770  		return fmt.Sprintf("tokenName:%s:info:%s", string(key[1:]), token.String())
   771  	case tokentypes.TokenNumberKey[0]:
   772  		var tokenNumber uint64
   773  		cdc.MustUnmarshalBinaryBare(value, &tokenNumber)
   774  		return fmt.Sprintf("tokenNumber:%d", tokenNumber)
   775  	case tokentypes.PrefixUserTokenKey[0]:
   776  		return fmt.Sprintf("address:%s;symbol:%s", key[1:21], string(key[21:]))
   777  	default:
   778  		return defaultKvFormatter(key, value)
   779  	}
   780  }
   781  
   782  func mainPrintKey(cdc *codec.Codec, key []byte, value []byte) string {
   783  	if bytes.Equal(key, []byte("consensus_params")) {
   784  		var cons abci.ConsensusParams
   785  		err := proto.Unmarshal(value, &cons)
   786  		if err != nil {
   787  			return fmt.Sprintf("consensusParams:%X; unmarshal error, %s", value, err)
   788  		}
   789  		return fmt.Sprintf("consensusParams:%s", cons.String())
   790  	}
   791  	return defaultKvFormatter(key, value)
   792  }
   793  
   794  func slashingPrintKey(cdc *codec.Codec, key []byte, value []byte) string {
   795  	switch key[0] {
   796  	case slashingtypes.ValidatorSigningInfoKey[0]:
   797  		var signingInfo slashingtypes.ValidatorSigningInfo
   798  		cdc.MustUnmarshalBinaryLengthPrefixed(value, &signingInfo)
   799  		return fmt.Sprintf("validatorAddr:%X;signingInfo:%s", key[1:], signingInfo.String())
   800  	case slashingtypes.ValidatorMissedBlockBitArrayKey[0]:
   801  		var index int64
   802  		index = int64(binary.LittleEndian.Uint64(key[len(key)-8:]))
   803  		var missed bool
   804  		cdc.MustUnmarshalBinaryLengthPrefixed(value, &missed)
   805  		return fmt.Sprintf("validatorMissedBlockAddr:%X;index:%d;missed:%v", key[1:len(key)-8], index, missed)
   806  	case slashingtypes.AddrPubkeyRelationKey[0]:
   807  		var pubkey crypto.PubKey
   808  		err := cdc.UnmarshalBinaryLengthPrefixed(value, &pubkey)
   809  		if err != nil {
   810  			return fmt.Sprintf("pubkeyAddr:%X;value %X unmarshal error, %s", key[1:], value, err)
   811  		} else {
   812  			return fmt.Sprintf("pubkeyAddr:%X;pubkey:%X", key[1:], pubkey.Bytes())
   813  		}
   814  	default:
   815  		return defaultKvFormatter(key, value)
   816  	}
   817  }
   818  
   819  func distributionPrintKey(cdc *codec.Codec, key []byte, value []byte) string {
   820  	switch key[0] {
   821  	case distypes.FeePoolKey[0]:
   822  		var feePool distypes.FeePool
   823  		cdc.MustUnmarshalBinaryLengthPrefixed(value, &feePool)
   824  		return fmt.Sprintf("feePool:%v", feePool)
   825  	case distypes.ProposerKey[0]:
   826  		var consAddr sdk.ConsAddress
   827  		cdc.MustUnmarshalBinaryLengthPrefixed(value, &consAddr)
   828  		return fmt.Sprintf("proposerKey consAddress:%X", consAddr)
   829  	case distypes.DelegatorWithdrawAddrPrefix[0]:
   830  		return fmt.Sprintf("delegatorWithdrawAddr:%X;address:%X", key[1:], value)
   831  	case distypes.ValidatorAccumulatedCommissionPrefix[0]:
   832  		var commission types.ValidatorAccumulatedCommission
   833  		cdc.MustUnmarshalBinaryLengthPrefixed(value, &commission)
   834  		return fmt.Sprintf("validatorAccumulatedAddr:%X;commission:%s", key[1:], commission.String())
   835  	default:
   836  		return defaultKvFormatter(key, value)
   837  	}
   838  }
   839  
   840  func govPrintKey(cdc *codec.Codec, key []byte, value []byte) string {
   841  	switch key[0] {
   842  	case govtypes.ProposalsKeyPrefix[0]:
   843  		var prop gov.Proposal
   844  		cdc.MustUnmarshalBinaryLengthPrefixed(value, &prop)
   845  		return fmt.Sprintf("proposalId:%d;proposal:%s", binary.BigEndian.Uint64(key[1:]), prop.String())
   846  	case govtypes.ActiveProposalQueuePrefix[0]:
   847  		time, _ := sdk.ParseTimeBytes(key[1:])
   848  		return fmt.Sprintf("activeProposalEndTime:%s;proposalId:%d", time.String(), binary.BigEndian.Uint64(value))
   849  	case govtypes.InactiveProposalQueuePrefix[0]:
   850  		time, _ := sdk.ParseTimeBytes(key[1:])
   851  		return fmt.Sprintf("inactiveProposalEndTime:%s;proposalId:%d", time.String(), binary.BigEndian.Uint64(value))
   852  	case govtypes.ProposalIDKey[0]:
   853  		if len(value) != 0 {
   854  			return fmt.Sprintf("proposalId:%d", binary.BigEndian.Uint64(value))
   855  		} else {
   856  			return fmt.Sprintf("proposalId:nil")
   857  		}
   858  	default:
   859  		return defaultKvFormatter(key, value)
   860  	}
   861  }
   862  
   863  func stakingPrintKey(cdc *codec.Codec, key []byte, value []byte) string {
   864  	switch key[0] {
   865  	case stakingtypes.LastValidatorPowerKey[0]:
   866  		var power int64
   867  		cdc.MustUnmarshalBinaryLengthPrefixed(value, &power)
   868  		return fmt.Sprintf("validatorAddress:%X;power:%d", key[1:], power)
   869  	case stakingtypes.LastTotalPowerKey[0]:
   870  		var power sdk.Int
   871  		cdc.MustUnmarshalBinaryLengthPrefixed(value, &power)
   872  		return fmt.Sprintf("lastTotolValidatorPower:%s", power.String())
   873  	case stakingtypes.ValidatorsKey[0]:
   874  		var validator stakingtypes.Validator
   875  		cdc.MustUnmarshalBinaryLengthPrefixed(value, &validator)
   876  		return fmt.Sprintf("validatorAddress:%X;validator:%s", key[1:], validator.String())
   877  	case stakingtypes.ValidatorsByConsAddrKey[0]:
   878  		return fmt.Sprintf("validatorConsAddr:%X;valAddress:%X", key[1:], value)
   879  	case stakingtypes.ValidatorsByPowerIndexKey[0]:
   880  		consensusPower := int64(binary.BigEndian.Uint64(key[1:9]))
   881  		operAddr := key[9:]
   882  		for i, b := range operAddr {
   883  			operAddr[i] = ^b
   884  		}
   885  		return fmt.Sprintf("validatorPowerIndex consensusPower:%d;operAddr:%X;operatorAddress:%X", consensusPower, operAddr, value)
   886  	default:
   887  		return defaultKvFormatter(key, value)
   888  	}
   889  }
   890  
   891  func paramsPrintKey(cdc *codec.Codec, key []byte, value []byte) string {
   892  	if bytes.Contains(key, []byte("custom")) {
   893  		length := len([]byte("custom/evm/"))
   894  		return evmPrintKey(cdc, key[length:], value)
   895  	}
   896  	return fmt.Sprintf("paramsKey:%s;value:%s", string(key), string(value))
   897  }
   898  
   899  func accPrintKey(cdc *codec.Codec, key []byte, value []byte) string {
   900  	if key[0] == acctypes.AddressStoreKeyPrefix[0] {
   901  		var acc exported.Account
   902  		cdc.MustUnmarshalBinaryBare(value, &acc)
   903  		return fmt.Sprintf("adress:%X;account:%s", key[1:], acc.String())
   904  	} else if bytes.Equal(key, acctypes.GlobalAccountNumberKey) {
   905  		var accNum uint64
   906  		cdc.MustUnmarshalBinaryLengthPrefixed(value, &accNum)
   907  		return fmt.Sprintf("%s:%d", string(key), accNum)
   908  	} else {
   909  		return defaultKvFormatter(key, value)
   910  	}
   911  }
   912  
   913  func evmPrintKey(cdc *codec.Codec, key []byte, value []byte) string {
   914  	switch key[0] {
   915  	case evmtypes.KeyPrefixBlockHash[0]:
   916  		blockHash := key[1:]
   917  		height := int64(binary.BigEndian.Uint64(value))
   918  		return fmt.Sprintf("blockHash:%X;height:%d", blockHash, height)
   919  	case evmtypes.KeyPrefixBloom[0]:
   920  		height := int64(binary.BigEndian.Uint64(key[1:]))
   921  		bloom := ethtypes.BytesToBloom(value)
   922  		return fmt.Sprintf("bloomHeight:%d;data:%X", height, bloom[:])
   923  	case evmtypes.KeyPrefixCode[0]:
   924  		return fmt.Sprintf("codeHash:%X;code:%X", key[1:], value)
   925  	case evmtypes.KeyPrefixStorage[0]:
   926  		return fmt.Sprintf("stroageAddr:%X;key:%X;data:%X", key[1:21], key[21:], value)
   927  	case evmtypes.KeyPrefixChainConfig[0]:
   928  		if len(value) != 0 {
   929  			var config evmtypes.ChainConfig
   930  			cdc.MustUnmarshalBinaryBare(value, &config)
   931  			return fmt.Sprintf("chainConfig:%s", config.String())
   932  		} else {
   933  			return fmt.Sprintf("chainConfig:nil")
   934  		}
   935  	case evmtypes.KeyPrefixHeightHash[0]:
   936  		height := binary.BigEndian.Uint64(key[1:])
   937  		return fmt.Sprintf("height:%d;blockHash:%X", height, value)
   938  	case evmtypes.KeyPrefixContractDeploymentWhitelist[0]:
   939  		return fmt.Sprintf("contractWhiteAddress:%X", key[1:])
   940  	case evmtypes.KeyPrefixContractBlockedList[0]:
   941  		return fmt.Sprintf("contractBlockedAddres:%X;methods:%s", key[1:], value)
   942  	default:
   943  		if bytes.HasPrefix(key, evmtypes.KeyPrefixEvmRootHash) {
   944  			return fmt.Sprintf("evmRootHash: %s", ethcmn.BytesToHash(value))
   945  		}
   946  		return defaultKvFormatter(key, value)
   947  	}
   948  }
   949  
   950  // ReadTree loads an iavl tree from the directory
   951  // If version is 0, load latest, otherwise, load named version
   952  // The prefix represents which iavl tree you want to read. The iaviwer will always set a prefix.
   953  func ReadTree(db dbm.DB, version int, prefix []byte, cacheSize int) (*iavl.MutableTree, error) {
   954  	if len(prefix) != 0 {
   955  		db = dbm.NewPrefixDB(db, prefix)
   956  	}
   957  
   958  	tree, err := iavl.NewMutableTree(db, cacheSize)
   959  	if err != nil {
   960  		return nil, err
   961  	}
   962  	_, err = tree.LoadVersion(int64(version))
   963  	return tree, err
   964  }
   965  
   966  // parseWeaveKey assumes a separating : where all in front should be ascii,
   967  // and all afterwards may be ascii or binary
   968  func parseWeaveKey(key []byte) string {
   969  	cut := bytes.IndexRune(key, ':')
   970  	if cut == -1 {
   971  		return encodeID(key)
   972  	}
   973  	prefix := key[:cut]
   974  	id := key[cut+1:]
   975  	return fmt.Sprintf("%s:%s", encodeID(prefix), encodeID(id))
   976  }
   977  
   978  // casts to a string if it is printable ascii, hex-encodes otherwise
   979  func encodeID(id []byte) string {
   980  	for _, b := range id {
   981  		if b < 0x20 || b >= 0x80 {
   982  			return strings.ToUpper(hex.EncodeToString(id))
   983  		}
   984  	}
   985  	return string(id)
   986  }