diff --git a/cli/cmd.go b/cli/cmd.go index fad9ee6687b..acc09465b08 100644 --- a/cli/cmd.go +++ b/cli/cmd.go @@ -71,6 +71,7 @@ var Commands = []*cli.Command{ WithCategory("basic", walletCmd), WithCategory("basic", clientCmd), WithCategory("basic", multisigCmd), + WithCategory("basic", verifRegCmd), WithCategory("basic", paychCmd), WithCategory("developer", AuthCmd), WithCategory("developer", MpoolCmd), diff --git a/cli/verifreg.go b/cli/verifreg.go new file mode 100644 index 00000000000..70d03df2695 --- /dev/null +++ b/cli/verifreg.go @@ -0,0 +1,276 @@ +package cli + +import ( + "context" + "fmt" + + verifreg4 "github.com/filecoin-project/specs-actors/v4/actors/builtin/verifreg" + + "github.com/filecoin-project/go-state-types/big" + "github.com/filecoin-project/lotus/api/v0api" + + "github.com/urfave/cli/v2" + "golang.org/x/xerrors" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/abi" + + "github.com/filecoin-project/lotus/blockstore" + "github.com/filecoin-project/lotus/build" + "github.com/filecoin-project/lotus/chain/actors" + "github.com/filecoin-project/lotus/chain/actors/adt" + "github.com/filecoin-project/lotus/chain/actors/builtin/verifreg" + "github.com/filecoin-project/lotus/chain/types" + cbor "github.com/ipfs/go-ipld-cbor" +) + +var verifRegCmd = &cli.Command{ + Name: "verifreg", + Usage: "Interact with the verified registry actor", + Flags: []cli.Flag{}, + Subcommands: []*cli.Command{ + verifRegVerifyClientCmd, + verifRegListVerifiersCmd, + verifRegListClientsCmd, + verifRegCheckClientCmd, + verifRegCheckVerifierCmd, + }, +} + +var verifRegVerifyClientCmd = &cli.Command{ + Name: "verify-client", + Usage: "give allowance to the specified verified client address", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "from", + Usage: "specify your verifier address to send the message from", + Required: true, + }, + }, + Action: func(cctx *cli.Context) error { + froms := cctx.String("from") + if froms == "" { + return fmt.Errorf("must specify from address with --from") + } + + fromk, err := address.NewFromString(froms) + if err != nil { + return err + } + + if cctx.Args().Len() != 2 { + return fmt.Errorf("must specify two arguments: address and allowance") + } + + target, err := address.NewFromString(cctx.Args().Get(0)) + if err != nil { + return err + } + + allowance, err := types.BigFromString(cctx.Args().Get(1)) + if err != nil { + return err + } + + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + found, dcap, err := checkVerifier(ctx, api, fromk) + if err != nil { + return err + } + + if !found { + return xerrors.New("sender address must be a verifier") + } + + if dcap.Cmp(allowance.Int) < 0 { + return xerrors.Errorf("cannot allot more allowance than verifier data cap: %s < %s", dcap, allowance) + } + + // TODO: This should be abstracted over actor versions + params, err := actors.SerializeParams(&verifreg4.AddVerifiedClientParams{Address: target, Allowance: allowance}) + if err != nil { + return err + } + + msg := &types.Message{ + To: verifreg.Address, + From: fromk, + Method: verifreg.Methods.AddVerifiedClient, + Params: params, + } + + smsg, err := api.MpoolPushMessage(ctx, msg, nil) + if err != nil { + return err + } + + fmt.Printf("message sent, now waiting on cid: %s\n", smsg.Cid()) + + mwait, err := api.StateWaitMsg(ctx, smsg.Cid(), build.MessageConfidence) + if err != nil { + return err + } + + if mwait.Receipt.ExitCode != 0 { + return fmt.Errorf("failed to add verified client: %d", mwait.Receipt.ExitCode) + } + + return nil + }, +} + +var verifRegListVerifiersCmd = &cli.Command{ + Name: "list-verifiers", + Usage: "list all verifiers", + Action: func(cctx *cli.Context) error { + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + act, err := api.StateGetActor(ctx, verifreg.Address, types.EmptyTSK) + if err != nil { + return err + } + + apibs := blockstore.NewAPIBlockstore(api) + store := adt.WrapStore(ctx, cbor.NewCborStore(apibs)) + + st, err := verifreg.Load(store, act) + if err != nil { + return err + } + return st.ForEachVerifier(func(addr address.Address, dcap abi.StoragePower) error { + _, err := fmt.Printf("%s: %s\n", addr, dcap) + return err + }) + }, +} + +var verifRegListClientsCmd = &cli.Command{ + Name: "list-clients", + Usage: "list all verified clients", + Action: func(cctx *cli.Context) error { + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + act, err := api.StateGetActor(ctx, verifreg.Address, types.EmptyTSK) + if err != nil { + return err + } + + apibs := blockstore.NewAPIBlockstore(api) + store := adt.WrapStore(ctx, cbor.NewCborStore(apibs)) + + st, err := verifreg.Load(store, act) + if err != nil { + return err + } + return st.ForEachClient(func(addr address.Address, dcap abi.StoragePower) error { + _, err := fmt.Printf("%s: %s\n", addr, dcap) + return err + }) + }, +} + +var verifRegCheckClientCmd = &cli.Command{ + Name: "check-client", + Usage: "check verified client remaining bytes", + Action: func(cctx *cli.Context) error { + if !cctx.Args().Present() { + return fmt.Errorf("must specify client address to check") + } + + caddr, err := address.NewFromString(cctx.Args().First()) + if err != nil { + return err + } + + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + dcap, err := api.StateVerifiedClientStatus(ctx, caddr, types.EmptyTSK) + if err != nil { + return err + } + if dcap == nil { + return xerrors.Errorf("client %s is not a verified client", err) + } + + fmt.Println(*dcap) + + return nil + }, +} + +var verifRegCheckVerifierCmd = &cli.Command{ + Name: "check-verifier", + Usage: "check verifiers remaining bytes", + Action: func(cctx *cli.Context) error { + if !cctx.Args().Present() { + return fmt.Errorf("must specify verifier address to check") + } + + vaddr, err := address.NewFromString(cctx.Args().First()) + if err != nil { + return err + } + + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + found, dcap, err := checkVerifier(ctx, api, vaddr) + if err != nil { + return err + } + if !found { + return fmt.Errorf("not found") + } + + fmt.Println(dcap) + + return nil + }, +} + +func checkVerifier(ctx context.Context, api v0api.FullNode, vaddr address.Address) (bool, abi.StoragePower, error) { + vid, err := api.StateLookupID(ctx, vaddr, types.EmptyTSK) + if err != nil { + return false, big.Zero(), err + } + + act, err := api.StateGetActor(ctx, verifreg.Address, types.EmptyTSK) + if err != nil { + return false, big.Zero(), err + } + + apibs := blockstore.NewAPIBlockstore(api) + store := adt.WrapStore(ctx, cbor.NewCborStore(apibs)) + + st, err := verifreg.Load(store, act) + if err != nil { + return false, big.Zero(), err + } + + return st.VerifierDataCap(vid) +} diff --git a/cmd/lotus-shed/verifreg.go b/cmd/lotus-shed/verifreg.go index 52e1aa1d627..7640e636a77 100644 --- a/cmd/lotus-shed/verifreg.go +++ b/cmd/lotus-shed/verifreg.go @@ -111,8 +111,9 @@ var verifRegAddVerifierCmd = &cli.Command{ } var verifRegVerifyClientCmd = &cli.Command{ - Name: "verify-client", - Usage: "make a given account a verified client", + Name: "verify-client", + Usage: "make a given account a verified client", + Hidden: true, Flags: []cli.Flag{ &cli.StringFlag{ Name: "from", @@ -120,6 +121,7 @@ var verifRegVerifyClientCmd = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { + fmt.Println("DEPRECATED: This behavior is being moved to `lotus verifreg`") froms := cctx.String("from") if froms == "" { return fmt.Errorf("must specify from address with --from") @@ -184,9 +186,11 @@ var verifRegVerifyClientCmd = &cli.Command{ } var verifRegListVerifiersCmd = &cli.Command{ - Name: "list-verifiers", - Usage: "list all verifiers", + Name: "list-verifiers", + Usage: "list all verifiers", + Hidden: true, Action: func(cctx *cli.Context) error { + fmt.Println("DEPRECATED: This behavior is being moved to `lotus verifreg`") api, closer, err := lcli.GetFullNodeAPI(cctx) if err != nil { return err @@ -214,9 +218,11 @@ var verifRegListVerifiersCmd = &cli.Command{ } var verifRegListClientsCmd = &cli.Command{ - Name: "list-clients", - Usage: "list all verified clients", + Name: "list-clients", + Usage: "list all verified clients", + Hidden: true, Action: func(cctx *cli.Context) error { + fmt.Println("DEPRECATED: This behavior is being moved to `lotus verifreg`") api, closer, err := lcli.GetFullNodeAPI(cctx) if err != nil { return err @@ -244,9 +250,11 @@ var verifRegListClientsCmd = &cli.Command{ } var verifRegCheckClientCmd = &cli.Command{ - Name: "check-client", - Usage: "check verified client remaining bytes", + Name: "check-client", + Usage: "check verified client remaining bytes", + Hidden: true, Action: func(cctx *cli.Context) error { + fmt.Println("DEPRECATED: This behavior is being moved to `lotus verifreg`") if !cctx.Args().Present() { return fmt.Errorf("must specify client address to check") } @@ -278,9 +286,11 @@ var verifRegCheckClientCmd = &cli.Command{ } var verifRegCheckVerifierCmd = &cli.Command{ - Name: "check-verifier", - Usage: "check verifiers remaining bytes", + Name: "check-verifier", + Usage: "check verifiers remaining bytes", + Hidden: true, Action: func(cctx *cli.Context) error { + fmt.Println("DEPRECATED: This behavior is being moved to `lotus verifreg`") if !cctx.Args().Present() { return fmt.Errorf("must specify verifier address to check") } diff --git a/documentation/en/cli-lotus.md b/documentation/en/cli-lotus.md index 69430916d84..f9eb3aac17c 100644 --- a/documentation/en/cli-lotus.md +++ b/documentation/en/cli-lotus.md @@ -15,11 +15,12 @@ COMMANDS: version Print version help, h Shows a list of commands or help for one command BASIC: - send Send funds between accounts - wallet Manage wallet - client Make deals, store data, retrieve data - msig Interact with a multisig wallet - paych Manage payment channels + send Send funds between accounts + wallet Manage wallet + client Make deals, store data, retrieve data + msig Interact with a multisig wallet + verifreg Interact with the verified registry actor + paych Manage payment channels DEVELOPER: auth Manage RPC permissions mpool Manage message pool @@ -1034,6 +1035,94 @@ OPTIONS: ``` +## lotus verifreg +``` +NAME: + lotus verifreg - Interact with the verified registry actor + +USAGE: + lotus verifreg command [command options] [arguments...] + +COMMANDS: + verify-client give allowance to the specified verified client address + list-verifiers list all verifiers + list-clients list all verified clients + check-client check verified client remaining bytes + check-verifier check verifiers remaining bytes + help, h Shows a list of commands or help for one command + +OPTIONS: + --help, -h show help (default: false) + --version, -v print the version (default: false) + +``` + +### lotus verifreg verify-client +``` +NAME: + lotus verifreg verify-client - give allowance to the specified verified client address + +USAGE: + lotus verifreg verify-client [command options] [arguments...] + +OPTIONS: + --from value specify your verifier address to send the message from + --help, -h show help (default: false) + +``` + +### lotus verifreg list-verifiers +``` +NAME: + lotus verifreg list-verifiers - list all verifiers + +USAGE: + lotus verifreg list-verifiers [command options] [arguments...] + +OPTIONS: + --help, -h show help (default: false) + +``` + +### lotus verifreg list-clients +``` +NAME: + lotus verifreg list-clients - list all verified clients + +USAGE: + lotus verifreg list-clients [command options] [arguments...] + +OPTIONS: + --help, -h show help (default: false) + +``` + +### lotus verifreg check-client +``` +NAME: + lotus verifreg check-client - check verified client remaining bytes + +USAGE: + lotus verifreg check-client [command options] [arguments...] + +OPTIONS: + --help, -h show help (default: false) + +``` + +### lotus verifreg check-verifier +``` +NAME: + lotus verifreg check-verifier - check verifiers remaining bytes + +USAGE: + lotus verifreg check-verifier [command options] [arguments...] + +OPTIONS: + --help, -h show help (default: false) + +``` + ## lotus paych ``` NAME: