diff --git a/cmd/lotus-shed/main.go b/cmd/lotus-shed/main.go index 1f4d953f9..9cb1cd32c 100644 --- a/cmd/lotus-shed/main.go +++ b/cmd/lotus-shed/main.go @@ -86,6 +86,7 @@ func main() { replayOfflineCmd, msgindexCmd, FevmAnalyticsCmd, + mismatchesCmd, } app := &cli.App{ diff --git a/cmd/lotus-shed/mismatches.go b/cmd/lotus-shed/mismatches.go new file mode 100644 index 000000000..8dd1be352 --- /dev/null +++ b/cmd/lotus-shed/mismatches.go @@ -0,0 +1,53 @@ +package main + +import ( + "fmt" + + lcli "github.com/filecoin-project/lotus/cli" + "github.com/urfave/cli/v2" +) + +var mismatchesCmd = &cli.Command{ + Name: "mismatches", + Description: "Walk up the chain, recomputing state, and reporting any mismatches", + Action: func(cctx *cli.Context) error { + srv, err := lcli.GetFullNodeServices(cctx) + if err != nil { + return err + } + defer srv.Close() //nolint:errcheck + + api := srv.FullNodeAPI() + ctx := lcli.ReqContext(cctx) + + checkTs, err := api.ChainHead(ctx) + if err != nil { + return err + } + + for checkTs.Height() != 0 { + if checkTs.Height()%10000 == 0 { + fmt.Println("Reached height ", checkTs.Height()) + } + + execTsk := checkTs.Parents() + execTs, err := api.ChainGetTipSet(ctx, execTsk) + if err != nil { + return err + } + + st, err := api.StateCompute(ctx, execTs.Height(), nil, execTsk) + if err != nil { + return err + } + + if st.Root != checkTs.ParentState() { + fmt.Println("consensus mismatch found at height ", execTs.Height()) + } + + checkTs = execTs + } + + return nil + }, +}