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 }