Skip to content

Commit

Permalink
feat: extend datacap expiration
Browse files Browse the repository at this point in the history
  • Loading branch information
mx819812523 committed Nov 29, 2023
1 parent 3d5bebc commit 0d64164
Show file tree
Hide file tree
Showing 2 changed files with 236 additions and 0 deletions.
215 changes: 215 additions & 0 deletions cli/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,14 @@ import (
"github.com/filecoin-project/go-fil-markets/storagemarket"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
builtin2 "github.com/filecoin-project/go-state-types/builtin"
verifregtypes "github.com/filecoin-project/go-state-types/builtin/v9/verifreg"

"github.com/filecoin-project/lotus/api"
lapi "github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/v0api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
"github.com/filecoin-project/lotus/chain/types"
Expand Down Expand Up @@ -85,6 +88,7 @@ var clientCmd = &cli.Command{
WithCategory("storage", clientListAsksCmd),
WithCategory("storage", clientDealStatsCmd),
WithCategory("storage", clientInspectDealCmd),
WithCategory("storage", clientExtendDealCmd),
WithCategory("data", clientImportCmd),
WithCategory("data", clientDropCmd),
WithCategory("data", clientLocalCmd),
Expand Down Expand Up @@ -1315,6 +1319,164 @@ var clientInspectDealCmd = &cli.Command{
},
}

var clientExtendDealCmd = &cli.Command{
Name: "extend",
Usage: "extend datacap expiration",
Flags: []cli.Flag{
&cli.Int64Flag{
Name: "max-term",
Usage: "datacap max term",
Required: true,
},
&cli.Uint64SliceFlag{
Name: "claimId",
Usage: "claim id array",
},
&cli.StringFlag{
Name: "from",
Usage: "address to send the message",
},
&cli.BoolFlag{
Name: "auto",
Usage: "automatically select eligible datacap renewals",
},
&cli.Int64Flag{
Name: "expiration-cutoff",
Usage: "when use --auto flag, skip datacap whose current expiration is more than <cutoff> epochs from now (infinity if unspecified)",
},
},
ArgsUsage: "<provider address>",
Action: func(cctx *cli.Context) error {
if cctx.Args().Len() == 0 {
return fmt.Errorf("must pass provider")
}

api, closer, err := GetFullNodeAPI(cctx)
if err != nil {
return err
}
defer closer()
ctx := ReqContext(cctx)

provider, err := address.NewFromString(cctx.Args().First())
if err != nil {
return fmt.Errorf("parse provider failed: %v", err)
}
providerID, err := addressToActorID(provider)
if err != nil {
return err
}

var fromAddr address.Address
if cctx.IsSet("from") {
fromAddr, err = address.NewFromString(cctx.String("from"))
if err != nil {
return err
}
} else {
fromAddr, err = api.WalletDefaultAddress(ctx)
if err != nil {
return err
}
}
idAddr, err := api.StateLookupID(ctx, fromAddr, types.EmptyTSK)
if err != nil {
return err
}
fromID, err := addressToActorID(idAddr)
if err != nil {
return err
}

termMax := abi.ChainEpoch(cctx.Int64("max-term"))
if termMax > verifregtypes.MaximumVerifiedAllocationTerm {
return fmt.Errorf("max term %d greater than %d", termMax, verifregtypes.MaximumVerifiedAllocationTerm)
}

head, err := api.ChainHead(ctx)
if err != nil {
return err
}
claims, err := api.StateGetClaims(ctx, provider, types.EmptyTSK)
if err != nil {
return err
}

claimTermsParams := &verifregtypes.ExtendClaimTermsParams{}
if cctx.Bool("auto") {
cutoff := abi.ChainEpoch(cctx.Int64("expiration-cutoff"))
for id, claim := range claims {
if err := checkClaim(ctx, api, head, provider, fromID, termMax, claim, cutoff); err != nil {
if !errors.Is(err, errNotNeedExtend) {
fmt.Printf("check claim %d error: %v\n", id, err)
}
continue
}
claimTermsParams.Terms = append(claimTermsParams.Terms, verifregtypes.ClaimTerm{
Provider: providerID,
ClaimId: id,
TermMax: termMax,
})
}
} else if cctx.IsSet("claimId") {
claimIds := cctx.Uint64Slice("claimId")
for _, id := range claimIds {
claim, ok := claims[verifregtypes.ClaimId(id)]
if !ok {
continue
}
if err := checkClaim(ctx, api, head, provider, fromID, termMax, claim, -1); err != nil {
if !errors.Is(err, errNotNeedExtend) {
fmt.Printf("check claim %d error: %v\n", id, err)
}
continue
}
claimTermsParams.Terms = append(claimTermsParams.Terms, verifregtypes.ClaimTerm{
Provider: providerID,
ClaimId: verifregtypes.ClaimId(id),
TermMax: termMax,
})
}
} else {
return fmt.Errorf("must pass --claimId flag or --auto flag")
}

if len(claimTermsParams.Terms) == 0 {
fmt.Println("no claim need extend")
return nil
}

params, err := actors.SerializeParams(claimTermsParams)
if err != nil {
return err
}

msg := types.Message{
From: fromAddr,
To: builtin2.VerifiedRegistryActorAddr,
Method: builtin2.MethodsVerifiedRegistry.ExtendClaimTerms,
Params: params,
}

msgCID, err := api.MpoolPushMessage(ctx, &msg, nil)
if err != nil {
return fmt.Errorf("push message error: %v", err)
}
fmt.Printf("wait message: %v\n", msgCID)

msgLookup, err := api.StateWaitMsg(ctx, msgCID.Cid(), build.MessageConfidence)
if err != nil {
return err
}

if msgLookup.Receipt.ExitCode.IsError() {
return fmt.Errorf("message execute error, exit code: %v", msgLookup.Receipt.ExitCode)
}

return nil
},
}

var clientDealStatsCmd = &cli.Command{
Name: "deal-stats",
Usage: "Print statistics about local storage deals",
Expand Down Expand Up @@ -2466,3 +2628,56 @@ func renderDeal(di *lapi.DealInfo) {
}
}
}

var errNotNeedExtend = fmt.Errorf("not need extend")

func checkClaim(ctx context.Context,
fapi v0api.FullNode,
head *types.TipSet,
provider address.Address,
fromID abi.ActorID,
termMax abi.ChainEpoch,
claim verifregtypes.Claim,
cutoff abi.ChainEpoch,
) error {
if claim.Client != fromID {
return fmt.Errorf("client %d not match form actor id %d", claim.Client, fromID)
}

if claim.TermMax >= termMax {
return fmt.Errorf("new term max(%d) smaller than old term max(%d)", termMax, claim.TermMax)
}
expiration := claim.TermStart + claim.TermMax - head.Height()
if expiration <= 0 {
// already expiration
return fmt.Errorf("claim already expiration")
}
// if cutoff is negative number, skip check
if cutoff >= 0 {
if expiration > cutoff {
return errNotNeedExtend
}
}

sectorExpiration, err := fapi.StateSectorExpiration(ctx, provider, claim.Sector, types.EmptyTSK)
if err != nil {
return fmt.Errorf("got sector %d expiration failed: %v", claim.Sector, err)
} else if sectorExpiration.OnTime <= head.Height() ||
(sectorExpiration.Early != 0 && sectorExpiration.Early <= head.Height()) {
return fmt.Errorf("sector already expiration")
}

return nil
}

func addressToActorID(addr address.Address) (abi.ActorID, error) {
if addr.Protocol() != address.ID {
return 0, fmt.Errorf("%s not id address", addr)
}
id, err := strconv.ParseUint(addr.String()[2:], 10, 64)
if err != nil {
return 0, err
}

return abi.ActorID(id), nil
}
21 changes: 21 additions & 0 deletions documentation/en/cli-lotus.md
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ COMMANDS:
list-asks List asks for top miners
deal-stats Print statistics about local storage deals
inspect-deal Inspect detailed information about deal's lifecycle and the various stages it goes through
extend extend datacap expiration
UTIL:
commP Calculate the piece-cid (commP) of a CAR file
generate-car Generate a car file from input
Expand Down Expand Up @@ -812,6 +813,26 @@ OPTIONS:
--help, -h show help
```

### lotus client extend
```
NAME:
lotus client extend - extend datacap expiration
USAGE:
lotus client extend [command options] <provider address>
CATEGORY:
STORAGE
OPTIONS:
--max-term value datacap max term (default: 0)
--claimId value [ --claimId value ] claim id array
--from value address to send the message
--auto automatically select eligible datacap renewals (default: false)
--expiration-cutoff value when use --auto flag, skip datacap whose current expiration is more than <cutoff> epochs from now (infinity if unspecified) (default: 0)
--help, -h show help
```

### lotus client commP
```
NAME:
Expand Down

0 comments on commit 0d64164

Please sign in to comment.