From 62fedfbce3feb078cff785b8550d97c3bcb7eafe Mon Sep 17 00:00:00 2001 From: Geoff Stuart Date: Mon, 14 Nov 2022 16:46:45 -0500 Subject: [PATCH] Make pre-migration optional --- cli/state.go | 4 +- cmd/lotus-shed/gas-estimation.go | 47 ++++++++++++---- cmd/lotus-shed/main.go | 2 +- cmd/lotus-shed/migrations.go | 96 +++++++++++++++++--------------- 4 files changed, 90 insertions(+), 59 deletions(-) diff --git a/cli/state.go b/cli/state.go index cd134b49d..83e452095 100644 --- a/cli/state.go +++ b/cli/state.go @@ -1355,7 +1355,7 @@ func ComputeStateHTMLTempl(w io.Writer, ts *types.TipSet, o *api.ComputeStateOut "IsSlow": isSlow, "IsVerySlow": isVerySlow, "IntExit": func(i exitcode.ExitCode) int64 { return int64(i) }, - "SumGas": sumGas, + "SumGas": SumGas, "CodeStr": codeStr, "Call": call, "PrintTiming": func() bool { return printTiming }, @@ -1423,7 +1423,7 @@ func isVerySlow(t time.Duration) bool { return t > 50*time.Millisecond } -func sumGas(changes []*types.GasTrace) types.GasTrace { +func SumGas(changes []*types.GasTrace) types.GasTrace { var out types.GasTrace for _, gc := range changes { out.TotalGas += gc.TotalGas diff --git a/cmd/lotus-shed/gas-estimation.go b/cmd/lotus-shed/gas-estimation.go index 6517ab5b3..02f256f2f 100644 --- a/cmd/lotus-shed/gas-estimation.go +++ b/cmd/lotus-shed/gas-estimation.go @@ -8,14 +8,13 @@ import ( "strconv" "text/tabwriter" - "github.com/filecoin-project/go-state-types/abi" - - "github.com/filecoin-project/go-state-types/network" - "github.com/ipfs/go-cid" "github.com/urfave/cli/v2" "golang.org/x/xerrors" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/network" + "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/beacon" "github.com/filecoin-project/lotus/chain/beacon/drand" @@ -29,9 +28,15 @@ import ( "github.com/filecoin-project/lotus/storage/sealer/ffiwrapper" ) -var gasEstimationCmd = &cli.Command{ - Name: "estimate-gas", - Description: "replay a message on the specified stateRoot and network version", +// USAGE: Sync a node, then call migrate-nv17 on some old state. Pass in the cid of the migrated state root, +// the epoch you migrated at, the network version you migrated to, and a message hash. You will be able to replay any +// message from between the migration epoch, and where your node originally synced to. Note: You may run into issues +// with nonces, or state that changed between the epoch you migrated at, and when the message was originally processed. +// This can be avoided by replaying messages from close to the migration epoch, or circumvented by using a custom +// FVM bundle. +var gasTraceCmd = &cli.Command{ + Name: "trace-gas", + Description: "replay a message on the specified stateRoot and network version to get an execution trace", ArgsUsage: "[migratedStateRootCid migrationEpoch networkVersion messageHash]", Flags: []cli.Flag{ &cli.StringFlag{ @@ -56,7 +61,7 @@ var gasEstimationCmd = &cli.Command{ return fmt.Errorf("failed to parse input: %w", err) } - nv, err := strconv.ParseInt(cctx.Args().Get(2), 10, 64) + nv, err := strconv.ParseInt(cctx.Args().Get(2), 10, 32) if err != nil { return fmt.Errorf("failed to parse input: %w", err) } @@ -131,11 +136,12 @@ var gasEstimationCmd = &cli.Command{ return err } - tw := tabwriter.NewWriter(os.Stdout, 2, 2, 2, ' ', 0) + tw := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', tabwriter.AlignRight) res, err := sm.CallAtStateAndVersion(ctx, msg, executionTs, stateRootCid, network.Version(nv)) if err != nil { return err } + fmt.Println("Total gas used ", res.MsgRct.GasUsed) printInternalExecutions(0, []types.ExecutionTrace{res.ExecutionTrace}, tw) return tw.Flush() @@ -144,10 +150,29 @@ var gasEstimationCmd = &cli.Command{ func printInternalExecutions(depth int, trace []types.ExecutionTrace, tw *tabwriter.Writer) { if depth == 0 { - _, _ = fmt.Fprintf(tw, "depth\tFrom\tTo\tValue\tMethod\tGasUsed\tExitCode\tReturn\n") + _, _ = fmt.Fprintf(tw, "Depth\tFrom\tTo\tMethod\tTotalGas\tComputeGas\tStorageGas\t\tExitCode\n") } for _, im := range trace { - _, _ = fmt.Fprintf(tw, "%d\t%s\t%s\t%s\t%d\t%d\t%d\t%x\n", depth, im.Msg.From, im.Msg.To, im.Msg.Value, im.Msg.Method, im.MsgRct.GasUsed, im.MsgRct.ExitCode, im.MsgRct.Return) + sumGas := lcli.SumGas(im.GasCharges) + _, _ = fmt.Fprintf(tw, "%d\t%s\t%s\t%d\t%d\t%d\t%d\t\t%d\n", depth, truncateString(im.Msg.From.String(), 10), truncateString(im.Msg.To.String(), 10), im.Msg.Method, sumGas.TotalGas, sumGas.ComputeGas, sumGas.StorageGas, im.MsgRct.ExitCode) printInternalExecutions(depth+1, im.Subcalls, tw) } } + +func truncateString(str string, length int) string { + if len(str) <= length { + return str + } + + truncated := "" + count := 0 + for _, char := range str { + truncated += string(char) + count++ + if count >= length { + break + } + } + truncated += "..." + return truncated +} diff --git a/cmd/lotus-shed/main.go b/cmd/lotus-shed/main.go index 1f1d57ebc..3b961f4ba 100644 --- a/cmd/lotus-shed/main.go +++ b/cmd/lotus-shed/main.go @@ -76,7 +76,7 @@ func main() { msigCmd, fip36PollCmd, invariantsCmd, - gasEstimationCmd, + gasTraceCmd, } app := &cli.App{ diff --git a/cmd/lotus-shed/migrations.go b/cmd/lotus-shed/migrations.go index 415faa16d..c25ced5b5 100644 --- a/cmd/lotus-shed/migrations.go +++ b/cmd/lotus-shed/migrations.go @@ -53,6 +53,9 @@ var migrationsCmd = &cli.Command{ Name: "repo", Value: "~/.lotus", }, + &cli.BoolFlag{ + Name: "skip-pre-migration", + }, &cli.BoolFlag{ Name: "check-invariants", }, @@ -119,45 +122,8 @@ var migrationsCmd = &cli.Command{ return err } - ts1, err := cs.GetTipsetByHeight(ctx, blk.Height-240, migrationTs, false) - if err != nil { - return err - } - startTime := time.Now() - err = filcns.PreUpgradeActorsV9(ctx, sm, cache, ts1.ParentState(), ts1.Height()-1, ts1) - if err != nil { - return err - } - - preMigration1Time := time.Since(startTime) - - ts2, err := cs.GetTipsetByHeight(ctx, blk.Height-15, migrationTs, false) - if err != nil { - return err - } - - startTime = time.Now() - - err = filcns.PreUpgradeActorsV9(ctx, sm, cache, ts2.ParentState(), ts2.Height()-1, ts2) - if err != nil { - return err - } - - preMigration2Time := time.Since(startTime) - - startTime = time.Now() - - newCid1, err := filcns.UpgradeActorsV9(ctx, sm, cache, nil, blk.ParentStateRoot, blk.Height-1, migrationTs) - if err != nil { - return err - } - - cachedMigrationTime := time.Since(startTime) - - startTime = time.Now() - newCid2, err := filcns.UpgradeActorsV9(ctx, sm, nv15.NewMemMigrationCache(), nil, blk.ParentStateRoot, blk.Height-1, migrationTs) if err != nil { return err @@ -165,18 +131,58 @@ var migrationsCmd = &cli.Command{ uncachedMigrationTime := time.Since(startTime) - if newCid1 != newCid2 { - return xerrors.Errorf("got different results with and without the cache: %s, %s", newCid1, - newCid2) - } - fmt.Println("migration height ", blk.Height-1) + fmt.Println("old cid ", blk.ParentStateRoot) fmt.Println("new cid ", newCid2) - fmt.Println("completed premigration 1, took ", preMigration1Time) - fmt.Println("completed premigration 2, took ", preMigration2Time) - fmt.Println("completed round actual (with cache), took ", cachedMigrationTime) fmt.Println("completed round actual (without cache), took ", uncachedMigrationTime) + if !cctx.IsSet("skip-pre-migration") { + startTime = time.Now() + + ts1, err := cs.GetTipsetByHeight(ctx, blk.Height-240, migrationTs, false) + if err != nil { + return err + } + + err = filcns.PreUpgradeActorsV9(ctx, sm, cache, ts1.ParentState(), ts1.Height()-1, ts1) + if err != nil { + return err + } + + preMigration1Time := time.Since(startTime) + + ts2, err := cs.GetTipsetByHeight(ctx, blk.Height-15, migrationTs, false) + if err != nil { + return err + } + + startTime = time.Now() + + err = filcns.PreUpgradeActorsV9(ctx, sm, cache, ts2.ParentState(), ts2.Height()-1, ts2) + if err != nil { + return err + } + + preMigration2Time := time.Since(startTime) + + startTime = time.Now() + + newCid1, err := filcns.UpgradeActorsV9(ctx, sm, cache, nil, blk.ParentStateRoot, blk.Height-1, migrationTs) + if err != nil { + return err + } + + cachedMigrationTime := time.Since(startTime) + + if newCid1 != newCid2 { + return xerrors.Errorf("got different results with and without the cache: %s, %s", newCid1, + newCid2) + } + fmt.Println("completed premigration 1, took ", preMigration1Time) + fmt.Println("completed premigration 2, took ", preMigration2Time) + fmt.Println("completed round actual (with cache), took ", cachedMigrationTime) + } + if cctx.Bool("check-invariants") { err = checkMigrationInvariants(ctx, blk.ParentStateRoot, newCid2, bs, blk.Height-1) if err != nil {