diff --git a/cli/state.go b/cli/state.go index 2ac2cd37c..e4d28d1af 100644 --- a/cli/state.go +++ b/cli/state.go @@ -769,6 +769,10 @@ var stateComputeStateCmd = &cli.Command{ Name: "show-trace", Usage: "print out full execution trace for given tipset", }, + &cli.BoolFlag{ + Name: "html", + Usage: "generate html report", + }, }, Action: func(cctx *cli.Context) error { api, closer, err := GetFullNodeAPI(cctx) @@ -818,6 +822,10 @@ var stateComputeStateCmd = &cli.Command{ return err } + if cctx.Bool("html") { + return computeStateHtml(stout) + } + fmt.Println("computed state cid: ", stout.Root) if cctx.Bool("show-trace") { for _, ir := range stout.Trace { @@ -836,6 +844,65 @@ func printInternalExecutions(prefix string, trace []*types.ExecutionResult) { } } +func computeStateHtml(o *api.ComputeStateOutput) error { + fmt.Printf(` + + + + +
State CID: %s
+
Calls
`, o.Root) + + for _, ir := range o.Trace { + fmt.Printf(`
+
%s -> %s (%s FIL), Method %d
+
Params: %x
+
Exit: %d, Return: %x
+`, ir.Msg.From, ir.Msg.To, types.FIL(ir.Msg.Value), ir.Msg.Method, ir.Msg.Params, ir.MsgRct.ExitCode, ir.MsgRct.ExitCode, ir.MsgRct.Return) + if ir.MsgRct.ExitCode != 0 { + fmt.Printf(`
Error:
%s
`, ir.Error) + } + + if len(ir.InternalExecutions) > 0 { + fmt.Println("
Internal executions:
") + printInternalExecutionsHtml(ir.InternalExecutions) + } + fmt.Println("
") + } + + fmt.Printf(` +`) + return nil +} + +func printInternalExecutionsHtml(trace []*types.ExecutionResult) { + for _, im := range trace { + fmt.Printf(`
+
%s -> %s (%s FIL), Method %d
+
Params: %x
+
Exit: %d, Return: %x
+`, im.Msg.From, im.Msg.To, types.FIL(im.Msg.Value), im.Msg.Method, im.Msg.Params, im.MsgRct.ExitCode, im.MsgRct.ExitCode, im.MsgRct.Return) + if im.MsgRct.ExitCode != 0 { + fmt.Printf(`
Error:
%s
`, im.Error) + } + if len(im.Subcalls) > 0 { + fmt.Println("
Subcalls:
") + printInternalExecutionsHtml(im.Subcalls) + } + fmt.Println("
") + } +} + var stateWaitMsgCmd = &cli.Command{ Name: "wait-msg", Usage: "Wait for a message to appear on chain",