compute-state: html: decode code / method names
This commit is contained in:
parent
2a2b63086a
commit
de701a06de
110
cli/state.go
110
cli/state.go
@ -9,28 +9,56 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
"github.com/docker/go-units"
|
||||||
|
"github.com/ipfs/go-cid"
|
||||||
|
"github.com/libp2p/go-libp2p-core/peer"
|
||||||
|
"github.com/multiformats/go-multihash"
|
||||||
|
cbg "github.com/whyrusleeping/cbor-gen"
|
||||||
|
"golang.org/x/xerrors"
|
||||||
|
"gopkg.in/urfave/cli.v2"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/specs-actors/actors/abi"
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
||||||
|
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
||||||
miner2 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
miner2 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
||||||
samsig "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
|
samsig "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
||||||
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
||||||
"github.com/libp2p/go-libp2p-core/peer"
|
|
||||||
"golang.org/x/xerrors"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
"github.com/filecoin-project/lotus/miner"
|
"github.com/filecoin-project/lotus/miner"
|
||||||
|
|
||||||
"github.com/docker/go-units"
|
|
||||||
"github.com/ipfs/go-cid"
|
|
||||||
cbg "github.com/whyrusleeping/cbor-gen"
|
|
||||||
"gopkg.in/urfave/cli.v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var methods = map[cid.Cid][]string{}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cidToMethods := map[cid.Cid]interface{}{
|
||||||
|
// builtin.SystemActorCodeID: builtin.MethodsSystem - apparently it doesn't have methods
|
||||||
|
builtin.InitActorCodeID: builtin.MethodsInit,
|
||||||
|
builtin.CronActorCodeID: builtin.MethodsCron,
|
||||||
|
builtin.AccountActorCodeID: builtin.MethodsAccount,
|
||||||
|
builtin.StoragePowerActorCodeID: builtin.MethodsPower,
|
||||||
|
builtin.StorageMinerActorCodeID: builtin.MethodsMiner,
|
||||||
|
builtin.StorageMarketActorCodeID: builtin.MethodsMarket,
|
||||||
|
builtin.PaymentChannelActorCodeID: builtin.MethodsPaych,
|
||||||
|
builtin.MultisigActorCodeID: builtin.MethodsMultisig,
|
||||||
|
builtin.RewardActorCodeID: builtin.MethodsReward,
|
||||||
|
builtin.VerifiedRegistryActorCodeID: builtin.MethodsVerifiedRegistry,
|
||||||
|
}
|
||||||
|
|
||||||
|
for c, m := range cidToMethods {
|
||||||
|
rt := reflect.TypeOf(m)
|
||||||
|
nf := rt.NumField()
|
||||||
|
|
||||||
|
methods[c] = append(methods[c], "Send")
|
||||||
|
for i := 0; i < nf; i++ {
|
||||||
|
methods[c] = append(methods[c], rt.Field(i).Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var stateCmd = &cli.Command{
|
var stateCmd = &cli.Command{
|
||||||
Name: "state",
|
Name: "state",
|
||||||
Usage: "Interact with and query filecoin chain state",
|
Usage: "Interact with and query filecoin chain state",
|
||||||
@ -823,7 +851,22 @@ var stateComputeStateCmd = &cli.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cctx.Bool("html") {
|
if cctx.Bool("html") {
|
||||||
return computeStateHtml(stout)
|
codeCache := map[address.Address]cid.Cid{}
|
||||||
|
getCode := func(addr address.Address) (cid.Cid, error) {
|
||||||
|
if c, found := codeCache[addr]; found {
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := api.StateGetActor(ctx, addr, ts.Key())
|
||||||
|
if err != nil {
|
||||||
|
return cid.Cid{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
codeCache[addr] = c.Code
|
||||||
|
return c.Code, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return computeStateHtml(stout, getCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("computed state cid: ", stout.Root)
|
fmt.Println("computed state cid: ", stout.Root)
|
||||||
@ -844,12 +887,22 @@ func printInternalExecutions(prefix string, trace []*types.ExecutionResult) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func computeStateHtml(o *api.ComputeStateOutput) error {
|
func codeStr(c cid.Cid) string {
|
||||||
|
cmh, err := multihash.Decode(c.Hash())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return string(cmh.Digest)
|
||||||
|
}
|
||||||
|
|
||||||
|
func computeStateHtml(o *api.ComputeStateOutput, getCode func(addr address.Address) (cid.Cid, error)) error {
|
||||||
fmt.Printf(`<html>
|
fmt.Printf(`<html>
|
||||||
<head>
|
<head>
|
||||||
<style>
|
<style>
|
||||||
html, body { font-family: monospace; }
|
html, body { font-family: monospace; }
|
||||||
|
a:link, a:visited { color: #004; }
|
||||||
pre { background: #ccc; }
|
pre { background: #ccc; }
|
||||||
|
code { background: #eee; }
|
||||||
.error { color: red; }
|
.error { color: red; }
|
||||||
.exit0 { color: green; }
|
.exit0 { color: green; }
|
||||||
.exec {
|
.exec {
|
||||||
@ -857,6 +910,9 @@ func computeStateHtml(o *api.ComputeStateOutput) error {
|
|||||||
border-left: 1px solid;
|
border-left: 1px solid;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
.exec:hover {
|
||||||
|
background: #fef;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -864,18 +920,25 @@ func computeStateHtml(o *api.ComputeStateOutput) error {
|
|||||||
<div>Calls</div>`, o.Root)
|
<div>Calls</div>`, o.Root)
|
||||||
|
|
||||||
for _, ir := range o.Trace {
|
for _, ir := range o.Trace {
|
||||||
|
toCode, err := getCode(ir.Msg.To)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("getting code for %s: %w", toCode, err)
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Printf(`<div class="exec">
|
fmt.Printf(`<div class="exec">
|
||||||
<div><b>%s</b> -> <b>%s</b> (%s FIL), Method %d</div>
|
<div><b>%s</b> -> <b>%s</b> (%s FIL), M%d</div>
|
||||||
<div>Params: %x</div>
|
<div><code>%s:%s(<a href="http://cbor.me/?bytes=%x">%x</a>)</code></div>
|
||||||
<div><span class="exit%d">Exit: <b>%d</b></span>, Return: %x</div>
|
<div><span class="exit%d">Exit: <b>%d</b></span>, Return: %x</div>
|
||||||
`, 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)
|
`, ir.Msg.From, ir.Msg.To, types.FIL(ir.Msg.Value), ir.Msg.Method, codeStr(toCode), methods[toCode][ir.Msg.Method], ir.Msg.Params, ir.Msg.Params, ir.MsgRct.ExitCode, ir.MsgRct.ExitCode, ir.MsgRct.Return)
|
||||||
if ir.MsgRct.ExitCode != 0 {
|
if ir.MsgRct.ExitCode != 0 {
|
||||||
fmt.Printf(`<div class="error">Error: <pre>%s</pre></div>`, ir.Error)
|
fmt.Printf(`<div class="error">Error: <pre>%s</pre></div>`, ir.Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ir.InternalExecutions) > 0 {
|
if len(ir.InternalExecutions) > 0 {
|
||||||
fmt.Println("<div>Internal executions:</div>")
|
fmt.Println("<div>Internal executions:</div>")
|
||||||
printInternalExecutionsHtml(ir.InternalExecutions)
|
if err := printInternalExecutionsHtml(ir.InternalExecutions, getCode); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fmt.Println("</div>")
|
fmt.Println("</div>")
|
||||||
}
|
}
|
||||||
@ -885,22 +948,31 @@ func computeStateHtml(o *api.ComputeStateOutput) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func printInternalExecutionsHtml(trace []*types.ExecutionResult) {
|
func printInternalExecutionsHtml(trace []*types.ExecutionResult, getCode func(addr address.Address) (cid.Cid, error)) error {
|
||||||
for _, im := range trace {
|
for _, im := range trace {
|
||||||
|
toCode, err := getCode(im.Msg.To)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("getting code for %s: %w", toCode, err)
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Printf(`<div class="exec">
|
fmt.Printf(`<div class="exec">
|
||||||
<div><b>%s</b> -> <b>%s</b> (%s FIL), Method %d</div>
|
<div><b>%s</b> -> <b>%s</b> (%s FIL), M%d</div>
|
||||||
<div>Params: %x</div>
|
<div><code>%s:%s(<a href="http://cbor.me/?bytes=%x">%x</a>)</code></div>
|
||||||
<div><span class="exit%d">Exit: <b>%d</b></span>, Return: %x</div>
|
<div><span class="exit%d">Exit: <b>%d</b></span>, Return: %x</div>
|
||||||
`, 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)
|
`, im.Msg.From, im.Msg.To, types.FIL(im.Msg.Value), im.Msg.Method, codeStr(toCode), methods[toCode][im.Msg.Method], im.Msg.Params, im.Msg.Params, im.MsgRct.ExitCode, im.MsgRct.ExitCode, im.MsgRct.Return)
|
||||||
if im.MsgRct.ExitCode != 0 {
|
if im.MsgRct.ExitCode != 0 {
|
||||||
fmt.Printf(`<div class="error">Error: <pre>%s</pre></div>`, im.Error)
|
fmt.Printf(`<div class="error">Error: <pre>%s</pre></div>`, im.Error)
|
||||||
}
|
}
|
||||||
if len(im.Subcalls) > 0 {
|
if len(im.Subcalls) > 0 {
|
||||||
fmt.Println("<div>Subcalls:</div>")
|
fmt.Println("<div>Subcalls:</div>")
|
||||||
printInternalExecutionsHtml(im.Subcalls)
|
if err := printInternalExecutionsHtml(im.Subcalls, getCode); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fmt.Println("</div>")
|
fmt.Println("</div>")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var stateWaitMsgCmd = &cli.Command{
|
var stateWaitMsgCmd = &cli.Command{
|
||||||
|
Loading…
Reference in New Issue
Block a user