Add a more flexible cli tool: sectors renew
This commit is contained in:
parent
075bb3b314
commit
e0777fed15
@ -1,6 +1,8 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
@ -40,6 +42,7 @@ var sectorsCmd = &cli.Command{
|
|||||||
sectorsUpdateCmd,
|
sectorsUpdateCmd,
|
||||||
sectorsPledgeCmd,
|
sectorsPledgeCmd,
|
||||||
sectorsCheckExpireCmd,
|
sectorsCheckExpireCmd,
|
||||||
|
sectorsRenewCmd,
|
||||||
sectorsExtendCmd,
|
sectorsExtendCmd,
|
||||||
sectorsTerminateCmd,
|
sectorsTerminateCmd,
|
||||||
sectorsRemoveCmd,
|
sectorsRemoveCmd,
|
||||||
@ -511,6 +514,265 @@ var sectorsCheckExpireCmd = &cli.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sectorsRenewCmd = &cli.Command{
|
||||||
|
Name: "renew",
|
||||||
|
Usage: "Renew expiring sectors while not exceeding each sector's max life",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.Int64Flag{
|
||||||
|
Name: "lower-cutoff",
|
||||||
|
Usage: "skip sectors whose current expiration is less than <lower-cutoff> epochs from now",
|
||||||
|
Value: 120,
|
||||||
|
},
|
||||||
|
&cli.Int64Flag{
|
||||||
|
Name: "upper-cutoff",
|
||||||
|
Usage: "skip sectors whose current expiration is more than <upper-cutoff> epochs from now",
|
||||||
|
Value: 86400,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "sector-file",
|
||||||
|
Usage: "Provide a file containing one sector number in each line, ignoring above selecting criteria",
|
||||||
|
},
|
||||||
|
&cli.Int64Flag{
|
||||||
|
Name: "extension",
|
||||||
|
Usage: "try to extend selected sectors by this number of epochs",
|
||||||
|
Value: 1555200,
|
||||||
|
},
|
||||||
|
&cli.Int64Flag{
|
||||||
|
Name: "new-expiration",
|
||||||
|
Usage: "try to extend selected sectors to this epoch, ignoring extension",
|
||||||
|
},
|
||||||
|
&cli.Int64Flag{
|
||||||
|
Name: "tolerance",
|
||||||
|
Usage: "don't try to extend sectors by fewer than this number of epochs",
|
||||||
|
Value: 20160,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "really-do-it",
|
||||||
|
Usage: "pass this flag to really renew sectors, otherwise will only print out json representation of parameters",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
api, nCloser, err := lcli.GetFullNodeAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer nCloser()
|
||||||
|
|
||||||
|
ctx := lcli.ReqContext(cctx)
|
||||||
|
|
||||||
|
maddr, err := getActorAddress(ctx, cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
head, err := api.ChainHead(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
currEpoch := head.Height()
|
||||||
|
|
||||||
|
nv, err := api.StateNetworkVersion(ctx, types.EmptyTSK)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
activeSet, err := api.StateMinerActiveSectors(ctx, maddr, types.EmptyTSK)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
activeSectorsInfo := make(map[abi.SectorNumber]*miner.SectorOnChainInfo, len(activeSet))
|
||||||
|
for _, info := range activeSet {
|
||||||
|
activeSectorsInfo[info.SectorNumber] = info
|
||||||
|
}
|
||||||
|
|
||||||
|
var sis []*miner.SectorOnChainInfo
|
||||||
|
|
||||||
|
if cctx.IsSet("sector-file") {
|
||||||
|
file, err := os.Open(cctx.String("sector-file"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := scanner.Text()
|
||||||
|
|
||||||
|
id, err := strconv.ParseUint(line, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("could not parse %s as sector id: %s", line, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
si, found := activeSectorsInfo[abi.SectorNumber(id)]
|
||||||
|
if !found {
|
||||||
|
return xerrors.Errorf("sector %d is not active", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
sis = append(sis, si)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
for _, si := range activeSet {
|
||||||
|
if si.Expiration >= currEpoch+abi.ChainEpoch(cctx.Int64("lower-cutoff")) &&
|
||||||
|
si.Expiration <= currEpoch+abi.ChainEpoch(cctx.Int64("upper-cutoff")) {
|
||||||
|
sis = append(sis, si)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extensions := map[miner.SectorLocation]map[abi.ChainEpoch][]uint64{}
|
||||||
|
|
||||||
|
withinTolerance := func(a, b abi.ChainEpoch) bool {
|
||||||
|
diff := a - b
|
||||||
|
if diff < 0 {
|
||||||
|
diff = -diff
|
||||||
|
}
|
||||||
|
|
||||||
|
return diff <= abi.ChainEpoch(cctx.Int64("tolerance"))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, si := range sis {
|
||||||
|
extension := abi.ChainEpoch(cctx.Int64("extension"))
|
||||||
|
newExp := si.Expiration + extension
|
||||||
|
|
||||||
|
if cctx.IsSet("new-expiration") {
|
||||||
|
newExp = abi.ChainEpoch(cctx.Int64("new-expiration"))
|
||||||
|
}
|
||||||
|
|
||||||
|
maxExtendNow := currEpoch + miner3.MaxSectorExpirationExtension
|
||||||
|
if newExp > maxExtendNow {
|
||||||
|
newExp = maxExtendNow
|
||||||
|
}
|
||||||
|
|
||||||
|
maxExp := si.Activation + policy.GetSectorMaxLifetime(si.SealProof, nv)
|
||||||
|
if newExp > maxExp {
|
||||||
|
newExp = maxExp
|
||||||
|
}
|
||||||
|
|
||||||
|
if newExp <= si.Expiration || withinTolerance(newExp, si.Expiration) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
l, err := api.StateSectorPartition(ctx, maddr, si.SectorNumber, types.EmptyTSK)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("getting sector location for sector %d: %w", si.SectorNumber, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if l == nil {
|
||||||
|
return xerrors.Errorf("sector %d not found in any partition", si.SectorNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
es, found := extensions[*l]
|
||||||
|
if !found {
|
||||||
|
ne := make(map[abi.ChainEpoch][]uint64)
|
||||||
|
ne[newExp] = []uint64{uint64(si.SectorNumber)}
|
||||||
|
extensions[*l] = ne
|
||||||
|
} else {
|
||||||
|
added := false
|
||||||
|
for exp := range es {
|
||||||
|
if withinTolerance(newExp, exp) {
|
||||||
|
es[exp] = append(es[exp], uint64(si.SectorNumber))
|
||||||
|
added = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !added {
|
||||||
|
es[newExp] = []uint64{uint64(si.SectorNumber)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var params []miner3.ExtendSectorExpirationParams
|
||||||
|
|
||||||
|
p := miner3.ExtendSectorExpirationParams{}
|
||||||
|
scount := 0
|
||||||
|
|
||||||
|
for l, exts := range extensions {
|
||||||
|
for newExp, numbers := range exts {
|
||||||
|
scount += len(numbers)
|
||||||
|
if scount > policy.GetAddressedSectorsMax(nv) || len(p.Extensions) == policy.GetDeclarationsMax(nv) {
|
||||||
|
params = append(params, p)
|
||||||
|
p = miner3.ExtendSectorExpirationParams{}
|
||||||
|
scount = len(numbers)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Extensions = append(p.Extensions, miner3.ExpirationExtension{
|
||||||
|
Deadline: l.Deadline,
|
||||||
|
Partition: l.Partition,
|
||||||
|
Sectors: bitfield.NewFromSet(numbers),
|
||||||
|
NewExpiration: newExp,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we have any sectors, then one last append is needed here
|
||||||
|
if scount != 0 {
|
||||||
|
params = append(params, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(params) == 0 {
|
||||||
|
fmt.Println("nothing to extend")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
mi, err := api.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("getting miner info: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stotal := 0
|
||||||
|
|
||||||
|
for _, p := range params {
|
||||||
|
scount := 0
|
||||||
|
for _, ext := range p.Extensions {
|
||||||
|
count, err := ext.Sectors.Count()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
scount += int(count)
|
||||||
|
}
|
||||||
|
fmt.Printf("Renewing %d sectors: ", scount)
|
||||||
|
stotal += scount
|
||||||
|
|
||||||
|
if !cctx.Bool("really-do-it") {
|
||||||
|
data, err := json.MarshalIndent(&p, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
fmt.Println(string(data))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
sp, aerr := actors.SerializeParams(&p)
|
||||||
|
if aerr != nil {
|
||||||
|
return xerrors.Errorf("serializing params: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
smsg, err := api.MpoolPushMessage(ctx, &types.Message{
|
||||||
|
From: mi.Worker,
|
||||||
|
To: maddr,
|
||||||
|
Method: miner.Methods.ExtendSectorExpiration,
|
||||||
|
Value: big.Zero(),
|
||||||
|
Params: sp,
|
||||||
|
}, nil)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("mpool push message: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(smsg.Cid())
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Totally %d sectors renewed\n", stotal)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
var sectorsExtendCmd = &cli.Command{
|
var sectorsExtendCmd = &cli.Command{
|
||||||
Name: "extend",
|
Name: "extend",
|
||||||
Usage: "Extend sector expiration",
|
Usage: "Extend sector expiration",
|
||||||
|
Loading…
Reference in New Issue
Block a user