package main import ( "fmt" "github.com/urfave/cli/v2" "github.com/ipfs/go-cid" "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" ) var staterootStatsCmd = &cli.Command{ Name: "stateroot-stats", Description: "Walk down the chain and collect stats-obj changes between tipsets", Flags: []cli.Flag{ &cli.StringFlag{ Name: "tipset", Usage: "specify tipset to start from", }, &cli.IntFlag{ Name: "count", Usage: "number of tipsets to count back", Value: 30, }, &cli.BoolFlag{ Name: "diff", Usage: "compare tipset with previous", Value: false, }, }, Action: func(cctx *cli.Context) error { api, closer, err := lcli.GetFullNodeAPI(cctx) if err != nil { return err } defer closer() ctx := lcli.ReqContext(cctx) ts, err := lcli.LoadTipSet(ctx, cctx, api) if err != nil { return err } if ts == nil { ts, err = api.ChainHead(ctx) if err != nil { return err } } fn := func(ts *types.TipSet) (cid.Cid, []cid.Cid) { blk := ts.Blocks()[0] strt := blk.ParentStateRoot cids := blk.Parents return strt, cids } count := cctx.Int("count") diff := cctx.Bool("diff") fmt.Printf("Height\tSize\tLinks\tObj\tBase\n") for i := 0; i < count; i++ { if ts.Height() == 0 { return nil } strt, cids := fn(ts) k := types.NewTipSetKey(cids...) ts, err = api.ChainGetTipSet(ctx, k) if err != nil { return err } pstrt, _ := fn(ts) if !diff { pstrt = cid.Undef } stats, err := api.ChainStatObj(ctx, strt, pstrt) if err != nil { return err } fmt.Printf("%d\t%d\t%d\t%s\t%s\n", ts.Height(), stats.Size, stats.Links, strt, pstrt) } return nil }, }