diff --git a/chain/exchange/client.go b/chain/exchange/client.go index 371c50aed..cb030bcf7 100644 --- a/chain/exchange/client.go +++ b/chain/exchange/client.go @@ -117,7 +117,7 @@ func (c *client) doRequest( res, err := c.sendRequestToPeer(ctx, peer, req) if err != nil { if !xerrors.Is(err, network.ErrNoConn) { - log.Warnf("could not connect to peer %s: %s", + log.Warnf("could not send request to peer %s: %s", peer.String(), err) } continue diff --git a/cli/chain.go b/cli/chain.go index 73b25324b..288793ee4 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -8,6 +8,7 @@ import ( "os" "os/exec" "path" + "sort" "strconv" "strings" "time" @@ -30,6 +31,7 @@ import ( "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/chain/stmgr" types "github.com/filecoin-project/lotus/chain/types" ) @@ -50,6 +52,7 @@ var chainCmd = &cli.Command{ chainExportCmd, slashConsensusFault, chainGasPriceCmd, + chainInspectUsage, }, } @@ -375,6 +378,118 @@ var chainSetHeadCmd = &cli.Command{ }, } +var chainInspectUsage = &cli.Command{ + Name: "inspect-usage", + Usage: "Inspect block space usage of a given tipset", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "tipset", + Usage: "specify tipset to view block space usage of", + Value: "@head", + }, + }, + Action: func(cctx *cli.Context) error { + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + ts, err := LoadTipSet(ctx, cctx, api) + if err != nil { + return err + } + + pmsgs, err := api.ChainGetParentMessages(ctx, ts.Blocks()[0].Cid()) + if err != nil { + return err + } + + codeCache := make(map[address.Address]cid.Cid) + + lookupActorCode := func(a address.Address) (cid.Cid, error) { + c, ok := codeCache[a] + if ok { + return c, nil + } + + act, err := api.StateGetActor(ctx, a, ts.Key()) + if err != nil { + return cid.Undef, err + } + + codeCache[a] = act.Code + return act.Code, nil + } + + bySender := make(map[string]int64) + byDest := make(map[string]int64) + byMethod := make(map[string]int64) + + var sum int64 + for _, m := range pmsgs { + bySender[m.Message.From.String()] += m.Message.GasLimit + byDest[m.Message.To.String()] += m.Message.GasLimit + sum += m.Message.GasLimit + + code, err := lookupActorCode(m.Message.To) + if err != nil { + return err + } + + mm := stmgr.MethodsMap[code][m.Message.Method] + + byMethod[mm.Name] += m.Message.GasLimit + + } + + type keyGasPair struct { + Key string + Gas int64 + } + + mapToSortedKvs := func(m map[string]int64) []keyGasPair { + var vals []keyGasPair + for k, v := range m { + vals = append(vals, keyGasPair{ + Key: k, + Gas: v, + }) + } + sort.Slice(vals, func(i, j int) bool { + return vals[i].Gas > vals[j].Gas + }) + return vals + } + + senderVals := mapToSortedKvs(bySender) + destVals := mapToSortedKvs(byDest) + methodVals := mapToSortedKvs(byMethod) + + fmt.Printf("Total Gas Limit: %d\n", sum) + fmt.Printf("By Sender:\n") + for i := 0; i < 10 && i < len(senderVals); i++ { + sv := senderVals[i] + fmt.Printf("%s\t%0.2f\t(%d)\n", sv.Key, (100*float64(sv.Gas))/float64(sum), sv.Gas) + } + fmt.Println() + fmt.Printf("By Receiver:\n") + for i := 0; i < 10 && i < len(destVals); i++ { + sv := destVals[i] + fmt.Printf("%s\t%0.2f\t(%d)\n", sv.Key, (100*float64(sv.Gas))/float64(sum), sv.Gas) + } + fmt.Println() + fmt.Printf("By Method:\n") + for i := 0; i < 10 && i < len(methodVals); i++ { + sv := methodVals[i] + fmt.Printf("%s\t%0.2f\t(%d)\n", sv.Key, (100*float64(sv.Gas))/float64(sum), sv.Gas) + } + + return nil + }, +} + var chainListCmd = &cli.Command{ Name: "list", Usage: "View a segment of the chain",