diff --git a/api/api_full.go b/api/api_full.go index f0ce741ec8b..ceb0518b8ae 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -393,10 +393,16 @@ type FullNode interface { // StateCompute is a flexible command that applies the given messages on the given tipset. // The messages are run as though the VM were at the provided height. StateCompute(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*ComputeStateOutput, error) + // StateVerifierStatus returns the data cap for the given address. + // Returns nil if there is no entry in the data cap table for the + // address. + StateVerifierStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) // StateVerifiedClientStatus returns the data cap for the given address. // Returns nil if there is no entry in the data cap table for the // address. StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) + // StateVerifiedClientStatus returns the address of the Verified Registry's root key + StateVerifiedRegistryRootKey(ctx context.Context, tsk types.TipSetKey) (address.Address, error) // StateDealProviderCollateralBounds returns the min and max collateral a storage provider // can issue. It takes the deal size and verified status as parameters. StateDealProviderCollateralBounds(context.Context, abi.PaddedPieceSize, bool, types.TipSetKey) (DealCollateralBounds, error) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index f9b232d1011..540603b2fa3 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -204,7 +204,9 @@ type FullNodeStruct struct { StateMinerSectorCount func(context.Context, address.Address, types.TipSetKey) (api.MinerSectors, error) `perm:"read"` StateListMessages func(ctx context.Context, match *types.Message, tsk types.TipSetKey, toht abi.ChainEpoch) ([]cid.Cid, error) `perm:"read"` StateCompute func(context.Context, abi.ChainEpoch, []*types.Message, types.TipSetKey) (*api.ComputeStateOutput, error) `perm:"read"` + StateVerifierStatus func(context.Context, address.Address, types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` StateVerifiedClientStatus func(context.Context, address.Address, types.TipSetKey) (*abi.StoragePower, error) `perm:"read"` + StateVerifiedRegistryRootKey func(ctx context.Context, tsk types.TipSetKey) (address.Address, error) `perm:"read"` StateDealProviderCollateralBounds func(context.Context, abi.PaddedPieceSize, bool, types.TipSetKey) (api.DealCollateralBounds, error) `perm:"read"` StateCirculatingSupply func(context.Context, types.TipSetKey) (api.CirculatingSupply, error) `perm:"read"` StateNetworkVersion func(context.Context, types.TipSetKey) (stnetwork.Version, error) `perm:"read"` @@ -899,10 +901,18 @@ func (c *FullNodeStruct) StateCompute(ctx context.Context, height abi.ChainEpoch return c.Internal.StateCompute(ctx, height, msgs, tsk) } +func (c *FullNodeStruct) StateVerifierStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) { + return c.Internal.StateVerifierStatus(ctx, addr, tsk) +} + func (c *FullNodeStruct) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) { return c.Internal.StateVerifiedClientStatus(ctx, addr, tsk) } +func (c *FullNodeStruct) StateVerifiedRegistryRootKey(ctx context.Context, tsk types.TipSetKey) (address.Address, error) { + return c.Internal.StateVerifiedRegistryRootKey(ctx, tsk) +} + func (c *FullNodeStruct) StateDealProviderCollateralBounds(ctx context.Context, size abi.PaddedPieceSize, verified bool, tsk types.TipSetKey) (api.DealCollateralBounds, error) { return c.Internal.StateDealProviderCollateralBounds(ctx, size, verified, tsk) } diff --git a/chain/actors/builtin/verifreg/v0.go b/chain/actors/builtin/verifreg/v0.go index c59a588114b..51ed3b45679 100644 --- a/chain/actors/builtin/verifreg/v0.go +++ b/chain/actors/builtin/verifreg/v0.go @@ -39,6 +39,10 @@ func getDataCap(store adt.Store, root cid.Cid, addr address.Address) (bool, abi. return true, dcap, nil } +func (s *state0) RootKey() (address.Address, error) { + return s.State.RootKey, nil +} + func (s *state0) VerifiedClientDataCap(addr address.Address) (bool, abi.StoragePower, error) { return getDataCap(s.store, s.State.VerifiedClients, addr) } diff --git a/chain/actors/builtin/verifreg/verifreg.go b/chain/actors/builtin/verifreg/verifreg.go index c861f862f21..95a60d1d99b 100644 --- a/chain/actors/builtin/verifreg/verifreg.go +++ b/chain/actors/builtin/verifreg/verifreg.go @@ -30,6 +30,7 @@ func Load(store adt.Store, act *types.Actor) (State, error) { type State interface { cbor.Marshaler + RootKey() (address.Address, error) VerifiedClientDataCap(address.Address) (bool, abi.StoragePower, error) VerifierDataCap(address.Address) (bool, abi.StoragePower, error) ForEachVerifier(func(addr address.Address, dcap abi.StoragePower) error) error diff --git a/cmd/lotus-shed/verifreg.go b/cmd/lotus-shed/verifreg.go index 3e2f34f4b14..860498302f9 100644 --- a/cmd/lotus-shed/verifreg.go +++ b/cmd/lotus-shed/verifreg.go @@ -3,6 +3,8 @@ package main import ( "fmt" + "github.com/filecoin-project/go-state-types/big" + "github.com/urfave/cli/v2" "golang.org/x/xerrors" @@ -37,29 +39,31 @@ var verifRegCmd = &cli.Command{ } var verifRegAddVerifierCmd = &cli.Command{ - Name: "add-verifier", - Usage: "make a given account a verifier", + Name: "add-verifier", + Usage: "make a given account a verifier", + ArgsUsage: " ", Action: func(cctx *cli.Context) error { - fromk, err := address.NewFromString("t3qfoulel6fy6gn3hjmbhpdpf6fs5aqjb5fkurhtwvgssizq4jey5nw4ptq5up6h7jk7frdvvobv52qzmgjinq") - if err != nil { - return err + if cctx.Args().Len() != 3 { + return fmt.Errorf("must specify three arguments: sender, verifier, and allowance") } - if cctx.Args().Len() != 2 { - return fmt.Errorf("must specify two arguments: address and allowance") + sender, err := address.NewFromString(cctx.Args().Get(0)) + if err != nil { + return err } - target, err := address.NewFromString(cctx.Args().Get(0)) + verifier, err := address.NewFromString(cctx.Args().Get(1)) if err != nil { return err } - allowance, err := types.BigFromString(cctx.Args().Get(1)) + allowance, err := types.BigFromString(cctx.Args().Get(2)) if err != nil { return err } - params, err := actors.SerializeParams(&verifreg0.AddVerifierParams{Address: target, Allowance: allowance}) + // TODO: ActorUpgrade: Abstract + params, err := actors.SerializeParams(&verifreg0.AddVerifierParams{Address: verifier, Allowance: allowance}) if err != nil { return err } @@ -71,21 +75,19 @@ var verifRegAddVerifierCmd = &cli.Command{ defer closer() ctx := lcli.ReqContext(cctx) - msg := &types.Message{ - To: verifreg.Address, - From: fromk, - Method: builtin0.MethodsVerifiedRegistry.AddVerifier, - Params: params, + vrk, err := api.StateVerifiedRegistryRootKey(ctx, types.EmptyTSK) + if err != nil { + return err } - smsg, err := api.MpoolPushMessage(ctx, msg, nil) + smsg, err := api.MsigPropose(ctx, vrk, verifreg.Address, big.Zero(), sender, uint64(builtin0.MethodsVerifiedRegistry.AddVerifier), params) if err != nil { return err } - fmt.Printf("message sent, now waiting on cid: %s\n", smsg.Cid()) + fmt.Printf("message sent, now waiting on cid: %s\n", smsg) - mwait, err := api.StateWaitMsg(ctx, smsg.Cid(), build.MessageConfidence) + mwait, err := api.StateWaitMsg(ctx, smsg, build.MessageConfidence) if err != nil { return err } @@ -94,6 +96,7 @@ var verifRegAddVerifierCmd = &cli.Command{ return fmt.Errorf("failed to add verifier: %d", mwait.Receipt.ExitCode) } + //TODO: Internal msg might still have failed return nil }, diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index 19774802e96..a80f0b3e50b 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -161,6 +161,8 @@ * [StateSectorPartition](#StateSectorPartition) * [StateSectorPreCommitInfo](#StateSectorPreCommitInfo) * [StateVerifiedClientStatus](#StateVerifiedClientStatus) + * [StateVerifiedRegistryRootKey](#StateVerifiedRegistryRootKey) + * [StateVerifierStatus](#StateVerifierStatus) * [StateWaitMsg](#StateWaitMsg) * [Sync](#Sync) * [SyncCheckBad](#SyncCheckBad) @@ -4155,6 +4157,53 @@ Returns nil if there is no entry in the data cap table for the address. +Perms: read + +Inputs: +```json +[ + "t01234", + [ + { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + { + "/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve" + } + ] +] +``` + +Response: `"0"` + +### StateVerifiedRegistryRootKey +StateVerifiedClientStatus returns the address of the Verified Registry's root key + + +Perms: read + +Inputs: +```json +[ + [ + { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + { + "/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve" + } + ] +] +``` + +Response: `"t01234"` + +### StateVerifierStatus +StateVerifierStatus returns the data cap for the given address. +Returns nil if there is no entry in the data cap table for the +address. + + Perms: read Inputs: diff --git a/node/impl/full/state.go b/node/impl/full/state.go index f8bf92a926f..e5bd9f9d88c 100644 --- a/node/impl/full/state.go +++ b/node/impl/full/state.go @@ -1021,11 +1021,42 @@ func (a *StateAPI) StateMinerAvailableBalance(ctx context.Context, maddr address return types.BigAdd(abal, vested), nil } +// StateVerifiedClientStatus returns the data cap for the given address. +// Returns zero if there is no entry in the data cap table for the +// address. +func (a *StateAPI) StateVerifierStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) { + act, err := a.StateGetActor(ctx, verifreg.Address, tsk) + if err != nil { + return nil, err + } + + aid, err := a.StateLookupID(ctx, addr, tsk) + if err != nil { + log.Warnf("lookup failure %v", err) + return nil, err + } + + vrs, err := verifreg.Load(a.StateManager.ChainStore().Store(ctx), act) + if err != nil { + return nil, xerrors.Errorf("failed to load verified registry state: %w", err) + } + + verified, dcap, err := vrs.VerifierDataCap(aid) + if err != nil { + return nil, xerrors.Errorf("looking up verifier: %w", err) + } + if !verified { + return nil, nil + } + + return &dcap, nil +} + // StateVerifiedClientStatus returns the data cap for the given address. // Returns zero if there is no entry in the data cap table for the // address. func (a *StateAPI) StateVerifiedClientStatus(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*abi.StoragePower, error) { - act, err := a.StateGetActor(ctx, builtin0.VerifiedRegistryActorAddr, tsk) + act, err := a.StateGetActor(ctx, verifreg.Address, tsk) if err != nil { return nil, err } @@ -1052,6 +1083,20 @@ func (a *StateAPI) StateVerifiedClientStatus(ctx context.Context, addr address.A return &dcap, nil } +func (a *StateAPI) StateVerifiedRegistryRootKey(ctx context.Context, tsk types.TipSetKey) (address.Address, error) { + vact, err := a.StateGetActor(ctx, verifreg.Address, tsk) + if err != nil { + return address.Undef, err + } + + vst, err := verifreg.Load(a.StateManager.ChainStore().Store(ctx), vact) + if err != nil { + return address.Undef, err + } + + return vst.RootKey() +} + var dealProviderCollateralNum = types.NewInt(110) var dealProviderCollateralDen = types.NewInt(100)