lotus/cmd/sptool/actor.go

142 lines
3.6 KiB
Go
Raw Normal View History

package main
import (
"fmt"
"os"
"strings"
"github.com/fatih/color"
"github.com/urfave/cli/v2"
"github.com/filecoin-project/go-address"
builtin2 "github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli"
"github.com/filecoin-project/lotus/cli/spcli"
"github.com/filecoin-project/lotus/lib/tablewriter"
)
var actorCmd = &cli.Command{
Name: "actor",
Usage: "Manage Filecoin Miner Actor Metadata",
Subcommands: []*cli.Command{
spcli.ActorSetAddrsCmd(SPTActorGetter),
spcli.ActorWithdrawCmd(SPTActorGetter),
spcli.ActorRepayDebtCmd(SPTActorGetter),
spcli.ActorSetPeeridCmd(SPTActorGetter),
spcli.ActorSetOwnerCmd(SPTActorGetter),
spcli.ActorControlCmd(SPTActorGetter, actorControlListCmd(SPTActorGetter)),
spcli.ActorProposeChangeWorkerCmd(SPTActorGetter),
spcli.ActorConfirmChangeWorkerCmd(SPTActorGetter),
spcli.ActorCompactAllocatedCmd(SPTActorGetter),
spcli.ActorProposeChangeBeneficiaryCmd(SPTActorGetter),
spcli.ActorConfirmChangeBeneficiaryCmd(SPTActorGetter),
spcli.ActorNewMinerCmd,
},
}
func actorControlListCmd(getActor spcli.ActorAddressGetter) *cli.Command {
return &cli.Command{
Name: "list",
Usage: "Get currently set control addresses. Note: This excludes most roles as they are not known to the immediate chain state.",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "verbose",
},
},
Action: func(cctx *cli.Context) error {
api, acloser, err := lcli.GetFullNodeAPIV1(cctx)
if err != nil {
return err
}
defer acloser()
ctx := lcli.ReqContext(cctx)
maddr, err := getActor(cctx)
if err != nil {
return err
}
mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
if err != nil {
return err
}
tw := tablewriter.New(
tablewriter.Col("name"),
tablewriter.Col("ID"),
tablewriter.Col("key"),
tablewriter.Col("use"),
tablewriter.Col("balance"),
)
post := map[address.Address]struct{}{}
for _, ca := range mi.ControlAddresses {
post[ca] = struct{}{}
}
printKey := func(name string, a address.Address) {
var actor *types.Actor
if actor, err = api.StateGetActor(ctx, a, types.EmptyTSK); err != nil {
fmt.Printf("%s\t%s: error getting actor: %s\n", name, a, err)
return
}
b := actor.Balance
var k = a
// 'a' maybe a 'robust', in that case, 'StateAccountKey' returns an error.
if builtin2.IsAccountActor(actor.Code) {
if k, err = api.StateAccountKey(ctx, a, types.EmptyTSK); err != nil {
fmt.Printf("%s\t%s: error getting account key: %s\n", name, a, err)
return
}
}
kstr := k.String()
if !cctx.Bool("verbose") {
if len(kstr) > 9 {
kstr = kstr[:6] + "..."
}
}
bstr := types.FIL(b).String()
switch {
case b.LessThan(types.FromFil(10)):
bstr = color.RedString(bstr)
case b.LessThan(types.FromFil(50)):
bstr = color.YellowString(bstr)
default:
bstr = color.GreenString(bstr)
}
var uses []string
if a == mi.Worker {
uses = append(uses, color.YellowString("other"))
}
if _, ok := post[a]; ok {
uses = append(uses, color.GreenString("post"))
}
tw.Write(map[string]interface{}{
"name": name,
"ID": a,
"key": kstr,
"use": strings.Join(uses, " "),
"balance": bstr,
})
}
printKey("owner", mi.Owner)
printKey("worker", mi.Worker)
printKey("beneficiary", mi.Beneficiary)
for i, ca := range mi.ControlAddresses {
printKey(fmt.Sprintf("control-%d", i), ca)
}
return tw.Flush(os.Stdout)
},
}
}