From dc8206e58101c37be7773ae2939945aea80f1df8 Mon Sep 17 00:00:00 2001 From: Aayush Date: Thu, 20 Oct 2022 13:10:45 -0400 Subject: [PATCH] Add more shed tools for migration checking --- cmd/lotus-shed/diff.go | 197 ++++++++++++++++++++++++++++++++++- cmd/lotus-shed/migrations.go | 39 ++++++- 2 files changed, 228 insertions(+), 8 deletions(-) diff --git a/cmd/lotus-shed/diff.go b/cmd/lotus-shed/diff.go index 22b54981f..39dc2915a 100644 --- a/cmd/lotus-shed/diff.go +++ b/cmd/lotus-shed/diff.go @@ -1,20 +1,211 @@ package main import ( + "context" "fmt" + "io" "github.com/ipfs/go-cid" "github.com/urfave/cli/v2" "golang.org/x/xerrors" + "github.com/filecoin-project/go-state-types/abi" + miner9 "github.com/filecoin-project/go-state-types/builtin/v9/miner" + + "github.com/filecoin-project/lotus/chain/store" "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" + "github.com/filecoin-project/lotus/node/repo" ) var diffCmd = &cli.Command{ - Name: "diff", - Usage: "diff state objects", - Subcommands: []*cli.Command{diffStateTrees}, + Name: "diff", + Usage: "diff state objects", + Subcommands: []*cli.Command{ + diffStateTrees, + diffMinerStates, + }, +} + +var diffMinerStates = &cli.Command{ + Name: "miner-states", + Usage: "diff two miner-states", + ArgsUsage: " ", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "repo", + Value: "~/.lotus", + }, + }, + Action: func(cctx *cli.Context) error { + ctx := context.TODO() + + if cctx.NArg() != 2 { + return lcli.IncorrectNumArgs(cctx) + } + + stCidA, err := cid.Decode(cctx.Args().First()) + if err != nil { + return fmt.Errorf("failed to parse input: %w", err) + } + + stCidB, err := cid.Decode(cctx.Args().Get(1)) + if err != nil { + return fmt.Errorf("failed to parse input: %w", err) + } + + fsrepo, err := repo.NewFS(cctx.String("repo")) + if err != nil { + return err + } + + lkrepo, err := fsrepo.Lock(repo.FullNode) + if err != nil { + return err + } + + defer lkrepo.Close() //nolint:errcheck + + bs, err := lkrepo.Blockstore(ctx, repo.UniversalBlockstore) + if err != nil { + return fmt.Errorf("failed to open blockstore: %w", err) + } + + defer func() { + if c, ok := bs.(io.Closer); ok { + if err := c.Close(); err != nil { + log.Warnf("failed to close blockstore: %s", err) + } + } + }() + + actorStore := store.ActorStore(ctx, bs) + + var minerStA miner9.State + if err = actorStore.Get(ctx, stCidA, &minerStA); err != nil { + return err + } + + var minerStB miner9.State + if err = actorStore.Get(ctx, stCidB, &minerStB); err != nil { + return err + } + + //minerCode, err := cid.Decode("bafk2bzacedxmikgiz7du7e36vzsbmmhhozdtsucjkdo4uzkhj7nacajm33rx4") + //if err != nil { + // return err + //} + // + //minerStIntA, err := miner.Load(actorStore, &types.Actor{Head: stCidA, Code: minerCode}) + //if err != nil { + // return err + //} + // + //minerStIntB, err := miner.Load(actorStore, &types.Actor{Head: stCidB, Code: minerCode}) + //if err != nil { + // return err + //} + // + //dlDiff, err := miner.DiffDeadlines(minerStIntA, minerStIntB) + //if err != nil { + // return err + //} + // + //fmt.Println(dlDiff) + + fmt.Println(minerStA.Deadlines) + fmt.Println(minerStB.Deadlines) + + minerDeadlinesA, err := minerStA.LoadDeadlines(actorStore) + if err != nil { + return err + } + + minerDeadlinesB, err := minerStB.LoadDeadlines(actorStore) + if err != nil { + return err + } + + for i, dACid := range minerDeadlinesA.Due { + dBCid := minerDeadlinesB.Due[i] + if dACid != dBCid { + fmt.Println("Difference at index ", i, dACid, " != ", dBCid) + dA, err := minerDeadlinesA.LoadDeadline(actorStore, uint64(i)) + if err != nil { + return err + } + + dB, err := minerDeadlinesB.LoadDeadline(actorStore, uint64(i)) + if err != nil { + return err + } + + if dA.SectorsSnapshot != dB.SectorsSnapshot { + fmt.Println("They differ at Sectors snapshot ", dA.SectorsSnapshot, " != ", dB.SectorsSnapshot) + + sectorsSnapshotA, err := miner9.LoadSectors(actorStore, dA.SectorsSnapshot) + if err != nil { + return err + } + sectorsSnapshotB, err := miner9.LoadSectors(actorStore, dB.SectorsSnapshot) + if err != nil { + return err + } + + if sectorsSnapshotA.Length() != sectorsSnapshotB.Length() { + fmt.Println("sector snapshots have different lengts!") + } + + var infoA miner9.SectorOnChainInfo + err = sectorsSnapshotA.ForEach(&infoA, func(i int64) error { + infoB, ok, err := sectorsSnapshotB.Get(abi.SectorNumber(i)) + if err != nil { + return err + } + + if !ok { + fmt.Println(i, "isn't found in infoB!!") + } + + if infoA.SimpleQAPower != infoB.SimpleQAPower { + fmt.Println("gfreak1") + } + + if infoA.SectorKeyCID != infoB.SectorKeyCID { + fmt.Println("gfreak2") + } + + if infoA.SealedCID != infoB.SealedCID { + fmt.Println("gfreak3") + } + + if !infoA.DealWeight.Equals(infoB.DealWeight) { + fmt.Println("Deal Weights differ! ", infoA.DealWeight, infoB.DealWeight) + } + + if !infoA.VerifiedDealWeight.Equals(infoB.VerifiedDealWeight) { + fmt.Println("Verified Deal Weights differ! ", infoA.VerifiedDealWeight, infoB.VerifiedDealWeight) + } + + infoStrA := fmt.Sprint(infoA) + infoStrB := fmt.Sprint(*infoB) + if infoStrA != infoStrB { + fmt.Println(infoStrA) + fmt.Println(infoStrB) + } + + return nil + }) + if err != nil { + return err + } + + } + } + } + + return nil + }, } var diffStateTrees = &cli.Command{ diff --git a/cmd/lotus-shed/migrations.go b/cmd/lotus-shed/migrations.go index 74d1999f0..b0fa1ba47 100644 --- a/cmd/lotus-shed/migrations.go +++ b/cmd/lotus-shed/migrations.go @@ -52,6 +52,9 @@ var migrationsCmd = &cli.Command{ Name: "repo", Value: "~/.lotus", }, + &cli.BoolFlag{ + Name: "check-invariants", + }, }, Action: func(cctx *cli.Context) error { ctx := context.TODO() @@ -172,17 +175,20 @@ var migrationsCmd = &cli.Command{ fmt.Println("completed round actual (with cache), took ", cachedMigrationTime) fmt.Println("completed round actual (without cache), took ", uncachedMigrationTime) - err = checkStateInvariants(ctx, blk.ParentStateRoot, newCid1, bs) - if err != nil { - return err + if cctx.Bool("check-invariants") { + err = checkStateInvariants(ctx, blk.ParentStateRoot, newCid1, bs, blk.Height-1) + if err != nil { + return err + } } return nil }, } -func checkStateInvariants(ctx context.Context, v8StateRoot cid.Cid, v9StateRoot cid.Cid, bs blockstore.Blockstore) error { - actorStore := store.ActorStore(ctx, blockstore.NewTieredBstore(bs, blockstore.NewMemorySync())) +func checkStateInvariants(ctx context.Context, v8StateRoot cid.Cid, v9StateRoot cid.Cid, bs blockstore.Blockstore, epoch abi.ChainEpoch) error { + actorStore := store.ActorStore(ctx, bs) + startTime := time.Now() stateTreeV8, err := state.LoadStateTree(actorStore, v8StateRoot) if err != nil { @@ -209,6 +215,29 @@ func checkStateInvariants(ctx context.Context, v8StateRoot cid.Cid, v9StateRoot return err } + // Load the state root. + //var stateRoot types.StateRoot + //if err := actorStore.Get(ctx, v9StateRoot, &stateRoot); err != nil { + // return xerrors.Errorf("failed to decode state root: %w", err) + //} + // + //actorCodeCids, err := actors.GetActorCodeIDs(actorstypes.Version9) + //if err != nil { + // return err + //} + // + //actorTree, err := builtin.LoadTree(actorStore, stateRoot.Actors) + //messages, err := v9.CheckStateInvariants(actorTree, epoch, actorCodeCids) + //if err != nil { + // return xerrors.Errorf("checking state invariants: %w", err) + //} + // + //for _, message := range messages.Messages() { + // fmt.Println("got the following error: ", message) + //} + + fmt.Println("completed invariant checks, took ", time.Since(startTime)) + return nil }