From 96014c78aead27732ab324f989914e54492a0a96 Mon Sep 17 00:00:00 2001 From: Aayush Date: Wed, 22 Feb 2023 15:01:55 -0500 Subject: [PATCH] feat: update renew-sectors with FIP-0045 logic --- .../actors/builtin/verifreg/actor.go.template | 1 + .../actors/builtin/verifreg/state.go.template | 21 +++ chain/actors/builtin/verifreg/v0.go | 6 + chain/actors/builtin/verifreg/v10.go | 18 +++ chain/actors/builtin/verifreg/v2.go | 6 + chain/actors/builtin/verifreg/v3.go | 6 + chain/actors/builtin/verifreg/v4.go | 6 + chain/actors/builtin/verifreg/v5.go | 6 + chain/actors/builtin/verifreg/v6.go | 6 + chain/actors/builtin/verifreg/v7.go | 6 + chain/actors/builtin/verifreg/v8.go | 6 + chain/actors/builtin/verifreg/v9.go | 18 +++ chain/actors/builtin/verifreg/verifreg.go | 1 + cmd/lotus-miner/sectors.go | 140 ++++++++++++++---- documentation/en/cli-lotus-miner.md | 3 +- go.mod | 2 +- go.sum | 4 +- 17 files changed, 225 insertions(+), 31 deletions(-) diff --git a/chain/actors/builtin/verifreg/actor.go.template b/chain/actors/builtin/verifreg/actor.go.template index 9f9efef922f..9b779a68df5 100644 --- a/chain/actors/builtin/verifreg/actor.go.template +++ b/chain/actors/builtin/verifreg/actor.go.template @@ -83,6 +83,7 @@ type State interface { GetAllocations(clientIdAddr address.Address) (map[AllocationId]Allocation, error) GetClaim(providerIdAddr address.Address, claimId ClaimId) (*Claim, bool, error) GetClaims(providerIdAddr address.Address) (map[ClaimId]Claim, error) + GetClaimIdsBySector(providerIdAddr address.Address) (map[abi.SectorNumber][]ClaimId, error) GetState() interface{} } diff --git a/chain/actors/builtin/verifreg/state.go.template b/chain/actors/builtin/verifreg/state.go.template index 526dff54eb5..adcbc22c2e4 100644 --- a/chain/actors/builtin/verifreg/state.go.template +++ b/chain/actors/builtin/verifreg/state.go.template @@ -170,6 +170,27 @@ func (s *state{{.v}}) GetClaims(providerIdAddr address.Address) (map[ClaimId]Cla {{end}} } +func (s *state{{.v}}) GetClaimIdsBySector(providerIdAddr address.Address) (map[abi.SectorNumber][]ClaimId, error) { +{{if (le .v 8)}} + return nil, xerrors.Errorf("unsupported in actors v{{.v}}") +{{else}} + v{{.v}}Map, err := s.LoadClaimsToMap(s.store, providerIdAddr) + + retMap := make(map[abi.SectorNumber][]ClaimId) + for k, v := range v{{.v}}Map { + claims, ok := retMap[v.Sector] + if !ok { + retMap[v.Sector] = []ClaimId{ClaimId(k)} + } else { + retMap[v.Sector] = append(claims, ClaimId(k)) + } + } + + return retMap, err + +{{end}} +} + func (s *state{{.v}}) ActorKey() string { return manifest.VerifregKey } diff --git a/chain/actors/builtin/verifreg/v0.go b/chain/actors/builtin/verifreg/v0.go index 8d97ebbc2e3..9913c42c0c6 100644 --- a/chain/actors/builtin/verifreg/v0.go +++ b/chain/actors/builtin/verifreg/v0.go @@ -118,6 +118,12 @@ func (s *state0) GetClaims(providerIdAddr address.Address) (map[ClaimId]Claim, e } +func (s *state0) GetClaimIdsBySector(providerIdAddr address.Address) (map[abi.SectorNumber][]ClaimId, error) { + + return nil, xerrors.Errorf("unsupported in actors v0") + +} + func (s *state0) ActorKey() string { return manifest.VerifregKey } diff --git a/chain/actors/builtin/verifreg/v10.go b/chain/actors/builtin/verifreg/v10.go index 63b161da340..256f4d2f888 100644 --- a/chain/actors/builtin/verifreg/v10.go +++ b/chain/actors/builtin/verifreg/v10.go @@ -134,6 +134,24 @@ func (s *state10) GetClaims(providerIdAddr address.Address) (map[ClaimId]Claim, } +func (s *state10) GetClaimIdsBySector(providerIdAddr address.Address) (map[abi.SectorNumber][]ClaimId, error) { + + v10Map, err := s.LoadClaimsToMap(s.store, providerIdAddr) + + retMap := make(map[abi.SectorNumber][]ClaimId) + for k, v := range v10Map { + claims, ok := retMap[v.Sector] + if !ok { + retMap[v.Sector] = []ClaimId{ClaimId(k)} + } else { + retMap[v.Sector] = append(claims, ClaimId(k)) + } + } + + return retMap, err + +} + func (s *state10) ActorKey() string { return manifest.VerifregKey } diff --git a/chain/actors/builtin/verifreg/v2.go b/chain/actors/builtin/verifreg/v2.go index 61c175c7ae8..31f7f775df2 100644 --- a/chain/actors/builtin/verifreg/v2.go +++ b/chain/actors/builtin/verifreg/v2.go @@ -118,6 +118,12 @@ func (s *state2) GetClaims(providerIdAddr address.Address) (map[ClaimId]Claim, e } +func (s *state2) GetClaimIdsBySector(providerIdAddr address.Address) (map[abi.SectorNumber][]ClaimId, error) { + + return nil, xerrors.Errorf("unsupported in actors v2") + +} + func (s *state2) ActorKey() string { return manifest.VerifregKey } diff --git a/chain/actors/builtin/verifreg/v3.go b/chain/actors/builtin/verifreg/v3.go index 5ba478500c9..3ea016fd5c3 100644 --- a/chain/actors/builtin/verifreg/v3.go +++ b/chain/actors/builtin/verifreg/v3.go @@ -119,6 +119,12 @@ func (s *state3) GetClaims(providerIdAddr address.Address) (map[ClaimId]Claim, e } +func (s *state3) GetClaimIdsBySector(providerIdAddr address.Address) (map[abi.SectorNumber][]ClaimId, error) { + + return nil, xerrors.Errorf("unsupported in actors v3") + +} + func (s *state3) ActorKey() string { return manifest.VerifregKey } diff --git a/chain/actors/builtin/verifreg/v4.go b/chain/actors/builtin/verifreg/v4.go index 3ad739f6810..464cc9fdc20 100644 --- a/chain/actors/builtin/verifreg/v4.go +++ b/chain/actors/builtin/verifreg/v4.go @@ -119,6 +119,12 @@ func (s *state4) GetClaims(providerIdAddr address.Address) (map[ClaimId]Claim, e } +func (s *state4) GetClaimIdsBySector(providerIdAddr address.Address) (map[abi.SectorNumber][]ClaimId, error) { + + return nil, xerrors.Errorf("unsupported in actors v4") + +} + func (s *state4) ActorKey() string { return manifest.VerifregKey } diff --git a/chain/actors/builtin/verifreg/v5.go b/chain/actors/builtin/verifreg/v5.go index 1ffe06f3f4a..17901dd23a9 100644 --- a/chain/actors/builtin/verifreg/v5.go +++ b/chain/actors/builtin/verifreg/v5.go @@ -119,6 +119,12 @@ func (s *state5) GetClaims(providerIdAddr address.Address) (map[ClaimId]Claim, e } +func (s *state5) GetClaimIdsBySector(providerIdAddr address.Address) (map[abi.SectorNumber][]ClaimId, error) { + + return nil, xerrors.Errorf("unsupported in actors v5") + +} + func (s *state5) ActorKey() string { return manifest.VerifregKey } diff --git a/chain/actors/builtin/verifreg/v6.go b/chain/actors/builtin/verifreg/v6.go index 9786838d11a..68fac64cb4d 100644 --- a/chain/actors/builtin/verifreg/v6.go +++ b/chain/actors/builtin/verifreg/v6.go @@ -119,6 +119,12 @@ func (s *state6) GetClaims(providerIdAddr address.Address) (map[ClaimId]Claim, e } +func (s *state6) GetClaimIdsBySector(providerIdAddr address.Address) (map[abi.SectorNumber][]ClaimId, error) { + + return nil, xerrors.Errorf("unsupported in actors v6") + +} + func (s *state6) ActorKey() string { return manifest.VerifregKey } diff --git a/chain/actors/builtin/verifreg/v7.go b/chain/actors/builtin/verifreg/v7.go index e63e277427c..e8f3ac73984 100644 --- a/chain/actors/builtin/verifreg/v7.go +++ b/chain/actors/builtin/verifreg/v7.go @@ -118,6 +118,12 @@ func (s *state7) GetClaims(providerIdAddr address.Address) (map[ClaimId]Claim, e } +func (s *state7) GetClaimIdsBySector(providerIdAddr address.Address) (map[abi.SectorNumber][]ClaimId, error) { + + return nil, xerrors.Errorf("unsupported in actors v7") + +} + func (s *state7) ActorKey() string { return manifest.VerifregKey } diff --git a/chain/actors/builtin/verifreg/v8.go b/chain/actors/builtin/verifreg/v8.go index a1edeba3487..89393c4d9cf 100644 --- a/chain/actors/builtin/verifreg/v8.go +++ b/chain/actors/builtin/verifreg/v8.go @@ -118,6 +118,12 @@ func (s *state8) GetClaims(providerIdAddr address.Address) (map[ClaimId]Claim, e } +func (s *state8) GetClaimIdsBySector(providerIdAddr address.Address) (map[abi.SectorNumber][]ClaimId, error) { + + return nil, xerrors.Errorf("unsupported in actors v8") + +} + func (s *state8) ActorKey() string { return manifest.VerifregKey } diff --git a/chain/actors/builtin/verifreg/v9.go b/chain/actors/builtin/verifreg/v9.go index bf6424ba73f..ce63c7f94b4 100644 --- a/chain/actors/builtin/verifreg/v9.go +++ b/chain/actors/builtin/verifreg/v9.go @@ -133,6 +133,24 @@ func (s *state9) GetClaims(providerIdAddr address.Address) (map[ClaimId]Claim, e } +func (s *state9) GetClaimIdsBySector(providerIdAddr address.Address) (map[abi.SectorNumber][]ClaimId, error) { + + v9Map, err := s.LoadClaimsToMap(s.store, providerIdAddr) + + retMap := make(map[abi.SectorNumber][]ClaimId) + for k, v := range v9Map { + claims, ok := retMap[v.Sector] + if !ok { + retMap[v.Sector] = []ClaimId{ClaimId(k)} + } else { + retMap[v.Sector] = append(claims, ClaimId(k)) + } + } + + return retMap, err + +} + func (s *state9) ActorKey() string { return manifest.VerifregKey } diff --git a/chain/actors/builtin/verifreg/verifreg.go b/chain/actors/builtin/verifreg/verifreg.go index 1380a9207c0..8e025b242d6 100644 --- a/chain/actors/builtin/verifreg/verifreg.go +++ b/chain/actors/builtin/verifreg/verifreg.go @@ -131,6 +131,7 @@ type State interface { GetAllocations(clientIdAddr address.Address) (map[AllocationId]Allocation, error) GetClaim(providerIdAddr address.Address, claimId ClaimId) (*Claim, bool, error) GetClaims(providerIdAddr address.Address) (map[ClaimId]Claim, error) + GetClaimIdsBySector(providerIdAddr address.Address) (map[abi.SectorNumber][]ClaimId, error) GetState() interface{} } diff --git a/cmd/lotus-miner/sectors.go b/cmd/lotus-miner/sectors.go index 6ff84b3faa5..2acb4c5476d 100644 --- a/cmd/lotus-miner/sectors.go +++ b/cmd/lotus-miner/sectors.go @@ -30,6 +30,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner" + "github.com/filecoin-project/lotus/chain/actors/builtin/verifreg" "github.com/filecoin-project/lotus/chain/actors/policy" "github.com/filecoin-project/lotus/chain/types" lcli "github.com/filecoin-project/lotus/cli" @@ -709,7 +710,7 @@ type PseudoExtendSectorExpirationParams struct { Extensions []PseudoExpirationExtension } -func NewPseudoExtendParams(p *miner.ExtendSectorExpirationParams) (*PseudoExtendSectorExpirationParams, error) { +func NewPseudoExtendParams(p *miner.ExtendSectorExpiration2Params) (*PseudoExtendSectorExpirationParams, error) { res := PseudoExtendSectorExpirationParams{} for _, ext := range p.Extensions { scount, err := ext.Sectors.Count() @@ -833,6 +834,10 @@ var sectorsExtendCmd = &cli.Command{ Name: "only-cc", Usage: "only extend CC sectors (useful for making sector ready for snap upgrade)", }, + &cli.BoolFlag{ + Name: "drop-claims", + Usage: "drop claims for sectors that can be extended, but only without their verified power claims", + }, &cli.Int64Flag{ Name: "tolerance", Usage: "don't try to extend sectors by fewer than this number of epochs, defaults to 7 days", @@ -845,7 +850,7 @@ var sectorsExtendCmd = &cli.Command{ }, &cli.Int64Flag{ Name: "max-sectors", - Usage: "the maximum number of sectors contained in each message message", + Usage: "the maximum number of sectors contained in each message", }, &cli.BoolFlag{ Name: "really-do-it", @@ -900,7 +905,8 @@ var sectorsExtendCmd = &cli.Command{ } tbs := blockstore.NewTieredBstore(blockstore.NewAPIBlockstore(fullApi), blockstore.NewMemory()) - mas, err := lminer.Load(adt.WrapStore(ctx, cbor.NewCborStore(tbs)), mact) + adtStore := adt.WrapStore(ctx, cbor.NewCborStore(tbs)) + mas, err := lminer.Load(adtStore, mact) if err != nil { return err } @@ -1051,44 +1057,124 @@ var sectorsExtendCmd = &cli.Command{ } } - var params []miner.ExtendSectorExpirationParams + verifregAct, err := fullApi.StateGetActor(ctx, builtin.VerifiedRegistryActorAddr, types.EmptyTSK) + if err != nil { + return xerrors.Errorf("failed to lookup verifreg actor: %w", err) + } + + verifregSt, err := verifreg.Load(adtStore, verifregAct) + if err != nil { + return xerrors.Errorf("failed to load verifreg state: %w", err) + } + + claimsMap, err := verifregSt.GetClaims(maddr) + if err != nil { + return xerrors.Errorf("failed to lookup claims for miner: %w", err) + } - p := miner.ExtendSectorExpirationParams{} + claimIdsBySector, err := verifregSt.GetClaimIdsBySector(maddr) + if err != nil { + return xerrors.Errorf("failed to lookup claim IDs by sector: %w", err) + } + + sectorsMax, err := policy.GetAddressedSectorsMax(nv) + if err != nil { + return err + } + + declMax, err := policy.GetDeclarationsMax(nv) + if err != nil { + return err + } + + addrSectors := sectorsMax + if cctx.Int("max-sectors") != 0 { + addrSectors = cctx.Int("max-sectors") + if addrSectors > sectorsMax { + return xerrors.Errorf("the specified max-sectors exceeds the maximum limit") + } + } + + var params []miner.ExtendSectorExpiration2Params + + p := miner.ExtendSectorExpiration2Params{} scount := 0 for l, exts := range extensions { for newExp, numbers := range exts { - scount += len(numbers) - var addrSectors int - sectorsMax, err := policy.GetAddressedSectorsMax(nv) - if err != nil { - return err - } - if cctx.Int("max-sectors") == 0 { - addrSectors = sectorsMax - } else { - addrSectors = cctx.Int("max-sectors") - if addrSectors > sectorsMax { - return xerrors.Errorf("the specified max-sectors exceeds the maximum limit") + ccSectorsToExtend := bitfield.New() + var sectorsWithClaims []miner.SectorClaim + for _, sectorNumber := range numbers { + claimIdsToMaintain := make([]verifreg.ClaimId, 0) + claimIdsToDrop := make([]verifreg.ClaimId, 0) + cannotExtendSector := false + claimIds, ok := claimIdsBySector[sectorNumber] + // Nothing to check, add to ccSectors + if !ok { + ccSectorsToExtend.Set(uint64(sectorNumber)) + } else { + for _, claimId := range claimIds { + claim, ok := claimsMap[claimId] + if !ok { + return xerrors.Errorf("failed to find claim for claimId %d", claimId) + } + claimExpiration := claim.TermStart + claim.TermMin + // can be maintained in the extended sector + if claimExpiration > newExp { + claimIdsToMaintain = append(claimIdsToMaintain, claimId) + } else { + sectorInfo, ok := activeSectorsInfo[sectorNumber] + if !ok { + return xerrors.Errorf("failed to find sector in active sector set: %w", err) + } + if !cctx.Bool("drop-claims") || + // FIP-0045 requires the claim minimum duration to have passed + currEpoch <= (claim.TermStart+claim.TermMin) || + // FIP-0045 requires the sector to be in its last 30 days of life + (currEpoch <= sectorInfo.Expiration-builtin.EndOfLifeClaimDropPeriod) { + fmt.Printf("skipping sector %d due to claim %d\n", sectorNumber, claimId) + cannotExtendSector = true + break + } + + claimIdsToDrop = append(claimIdsToDrop, claimId) + } + } + if cannotExtendSector { + continue + } + + if len(claimIdsToMaintain)+len(claimIdsToDrop) != 0 { + sectorsWithClaims = append(sectorsWithClaims, miner.SectorClaim{ + SectorNumber: sectorNumber, + MaintainClaims: claimIdsToMaintain, + DropClaims: claimIdsToDrop, + }) + } } } - declMax, err := policy.GetDeclarationsMax(nv) + ccCount, err := ccSectorsToExtend.Count() if err != nil { - return err + return xerrors.Errorf("failed to count cc sectors: %w", err) } - if scount > addrSectors || len(p.Extensions) == declMax { + + sectorsInDecl := int(ccCount) + len(sectorsWithClaims) + + if scount+sectorsInDecl > addrSectors || len(p.Extensions) >= declMax { params = append(params, p) - p = miner.ExtendSectorExpirationParams{} - scount = len(numbers) + p = miner.ExtendSectorExpiration2Params{} + scount = sectorsInDecl } - p.Extensions = append(p.Extensions, miner.ExpirationExtension{ - Deadline: l.Deadline, - Partition: l.Partition, - Sectors: SectorNumsToBitfield(numbers), - NewExpiration: newExp, + p.Extensions = append(p.Extensions, miner.ExpirationExtension2{ + Deadline: l.Deadline, + Partition: l.Partition, + Sectors: SectorNumsToBitfield(numbers), + SectorsWithClaims: sectorsWithClaims, + NewExpiration: newExp, }) + } } diff --git a/documentation/en/cli-lotus-miner.md b/documentation/en/cli-lotus-miner.md index 94fec03fd29..14839160bce 100644 --- a/documentation/en/cli-lotus-miner.md +++ b/documentation/en/cli-lotus-miner.md @@ -1889,11 +1889,12 @@ USAGE: lotus-miner sectors extend [command options] OPTIONS: + --drop-claims drop claims for sectors that can be extended, but only without their verified power claims (default: false) --exclude value optionally provide a file containing excluding sectors --extension value try to extend selected sectors by this number of epochs, defaults to 540 days (default: 1555200) --from value only consider sectors whose current expiration epoch is in the range of [from, to], defaults to: now + 120 (1 hour) (default: 0) --max-fee value use up to this amount of FIL for one message. pass this flag to avoid message congestion. (default: "0") - --max-sectors value the maximum number of sectors contained in each message message (default: 0) + --max-sectors value the maximum number of sectors contained in each message (default: 0) --new-expiration value try to extend selected sectors to this epoch, ignoring extension (default: 0) --only-cc only extend CC sectors (useful for making sector ready for snap upgrade) (default: false) --really-do-it pass this flag to really extend sectors, otherwise will only print out json representation of parameters (default: false) diff --git a/go.mod b/go.mod index e96dab9d0ae..6a784c5adfb 100644 --- a/go.mod +++ b/go.mod @@ -44,7 +44,7 @@ require ( github.com/filecoin-project/go-legs v0.4.4 github.com/filecoin-project/go-padreader v0.0.1 github.com/filecoin-project/go-paramfetch v0.0.4 - github.com/filecoin-project/go-state-types v0.10.0-rc3 + github.com/filecoin-project/go-state-types v0.10.0-rc3.0.20230222200056-67d56f8d88ba github.com/filecoin-project/go-statemachine v1.0.2 github.com/filecoin-project/go-statestore v0.2.0 github.com/filecoin-project/go-storedcounter v0.1.0 diff --git a/go.sum b/go.sum index 4ae390bf907..eeba574f019 100644 --- a/go.sum +++ b/go.sum @@ -356,8 +356,8 @@ github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psS github.com/filecoin-project/go-state-types v0.1.6/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= github.com/filecoin-project/go-state-types v0.1.8/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= github.com/filecoin-project/go-state-types v0.1.10/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q= -github.com/filecoin-project/go-state-types v0.10.0-rc3 h1:qExCc2swTe5ndsiu9dEoMqIwppjuTNRbsAFgpzHnHbc= -github.com/filecoin-project/go-state-types v0.10.0-rc3/go.mod h1:aLIas+W8BWAfpLWEPUOGMPBdhcVwoCG4pIQSQk26024= +github.com/filecoin-project/go-state-types v0.10.0-rc3.0.20230222200056-67d56f8d88ba h1:BVODYayOrRMpejkWAMAxl9uohWq1s3Gm/wkfXbdPF8M= +github.com/filecoin-project/go-state-types v0.10.0-rc3.0.20230222200056-67d56f8d88ba/go.mod h1:aLIas+W8BWAfpLWEPUOGMPBdhcVwoCG4pIQSQk26024= github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig= github.com/filecoin-project/go-statemachine v1.0.2 h1:421SSWBk8GIoCoWYYTE/d+qCWccgmRH0uXotXRDjUbc= github.com/filecoin-project/go-statemachine v1.0.2/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54=