github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/builtin/miner/miner_state.go (about) 1 package miner 2 3 import ( 4 "fmt" 5 "reflect" 6 "sort" 7 8 addr "github.com/filecoin-project/go-address" 9 "github.com/filecoin-project/go-bitfield" 10 "github.com/filecoin-project/go-state-types/abi" 11 "github.com/filecoin-project/go-state-types/big" 12 "github.com/filecoin-project/go-state-types/dline" 13 xc "github.com/filecoin-project/go-state-types/exitcode" 14 cid "github.com/ipfs/go-cid" 15 errors "github.com/pkg/errors" 16 xerrors "golang.org/x/xerrors" 17 18 "github.com/filecoin-project/specs-actors/v4/actors/builtin" 19 "github.com/filecoin-project/specs-actors/v4/actors/util/adt" 20 ) 21 22 // Balance of Miner Actor should be greater than or equal to 23 // the sum of PreCommitDeposits and LockedFunds. 24 // It is possible for balance to fall below the sum of 25 // PCD, LF and InitialPledgeRequirements, and this is a bad 26 // state (IP Debt) that limits a miner actor's behavior (i.e. no balance withdrawals) 27 // Excess balance as computed by st.GetAvailableBalance will be 28 // withdrawable or usable for pre-commit deposit or pledge lock-up. 29 type State struct { 30 // Information not related to sectors. 31 Info cid.Cid 32 33 PreCommitDeposits abi.TokenAmount // Total funds locked as PreCommitDeposits 34 LockedFunds abi.TokenAmount // Total rewards and added funds locked in vesting table 35 36 VestingFunds cid.Cid // VestingFunds (Vesting Funds schedule for the miner). 37 38 FeeDebt abi.TokenAmount // Absolute value of debt this miner owes from unpaid fees 39 40 InitialPledge abi.TokenAmount // Sum of initial pledge requirements of all active sectors 41 42 // Sectors that have been pre-committed but not yet proven. 43 PreCommittedSectors cid.Cid // Map, HAMT[SectorNumber]SectorPreCommitOnChainInfo 44 45 // PreCommittedSectorsExpiry maintains the state required to expire PreCommittedSectors. 46 PreCommittedSectorsExpiry cid.Cid // BitFieldQueue (AMT[Epoch]*BitField) 47 48 // Allocated sector IDs. Sector IDs can never be reused once allocated. 49 AllocatedSectors cid.Cid // BitField 50 51 // Information for all proven and not-yet-garbage-collected sectors. 52 // 53 // Sectors are removed from this AMT when the partition to which the 54 // sector belongs is compacted. 55 Sectors cid.Cid // Array, AMT[SectorNumber]SectorOnChainInfo (sparse) 56 57 // DEPRECATED. This field will change names and no longer be updated every proving period in a future upgrade 58 // The first epoch in this miner's current proving period. This is the first epoch in which a PoSt for a 59 // partition at the miner's first deadline may arrive. Alternatively, it is after the last epoch at which 60 // a PoSt for the previous window is valid. 61 // Always greater than zero, this may be greater than the current epoch for genesis miners in the first 62 // WPoStProvingPeriod epochs of the chain; the epochs before the first proving period starts are exempt from Window 63 // PoSt requirements. 64 // Updated at the end of every period by a cron callback. 65 ProvingPeriodStart abi.ChainEpoch 66 67 // DEPRECATED. This field will be removed from state in a future upgrade. 68 // Index of the deadline within the proving period beginning at ProvingPeriodStart that has not yet been 69 // finalized. 70 // Updated at the end of each deadline window by a cron callback. 71 CurrentDeadline uint64 72 73 // The sector numbers due for PoSt at each deadline in the current proving period, frozen at period start. 74 // New sectors are added and expired ones removed at proving period boundary. 75 // Faults are not subtracted from this in state, but on the fly. 76 Deadlines cid.Cid 77 78 // Deadlines with outstanding fees for early sector termination. 79 EarlyTerminations bitfield.BitField 80 81 // True when miner cron is active, false otherwise 82 DeadlineCronActive bool 83 } 84 85 // Bitwidth of AMTs determined empirically from mutation patterns and projections of mainnet data. 86 const PrecommitExpiryAmtBitwidth = 6 87 const SectorsAmtBitwidth = 5 88 89 type MinerInfo struct { 90 // Account that owns this miner. 91 // - Income and returned collateral are paid to this address. 92 // - This address is also allowed to change the worker address for the miner. 93 Owner addr.Address // Must be an ID-address. 94 95 // Worker account for this miner. 96 // The associated pubkey-type address is used to sign blocks and messages on behalf of this miner. 97 Worker addr.Address // Must be an ID-address. 98 99 // Additional addresses that are permitted to submit messages controlling this actor (optional). 100 ControlAddresses []addr.Address // Must all be ID addresses. 101 102 PendingWorkerKey *WorkerKeyChange 103 104 // Byte array representing a Libp2p identity that should be used when connecting to this miner. 105 PeerId abi.PeerID 106 107 // Slice of byte arrays representing Libp2p multi-addresses used for establishing a connection with this miner. 108 Multiaddrs []abi.Multiaddrs 109 110 // The proof type used for Window PoSt for this miner. 111 // A miner may commit sectors with different seal proof types (but compatible sector size and 112 // corresponding PoSt proof types). 113 WindowPoStProofType abi.RegisteredPoStProof 114 115 // Amount of space in each sector committed by this miner. 116 // This is computed from the proof type and represented here redundantly. 117 SectorSize abi.SectorSize 118 119 // The number of sectors in each Window PoSt partition (proof). 120 // This is computed from the proof type and represented here redundantly. 121 WindowPoStPartitionSectors uint64 122 123 // The next epoch this miner is eligible for certain permissioned actor methods 124 // and winning block elections as a result of being reported for a consensus fault. 125 ConsensusFaultElapsed abi.ChainEpoch 126 127 // A proposed new owner account for this miner. 128 // Must be confirmed by a message from the pending address itself. 129 PendingOwnerAddress *addr.Address 130 } 131 132 type WorkerKeyChange struct { 133 NewWorker addr.Address // Must be an ID address 134 EffectiveAt abi.ChainEpoch 135 } 136 137 // Information provided by a miner when pre-committing a sector. 138 type SectorPreCommitInfo struct { 139 SealProof abi.RegisteredSealProof 140 SectorNumber abi.SectorNumber 141 SealedCID cid.Cid `checked:"true"` // CommR 142 SealRandEpoch abi.ChainEpoch 143 DealIDs []abi.DealID 144 Expiration abi.ChainEpoch 145 ReplaceCapacity bool // Whether to replace a "committed capacity" no-deal sector (requires non-empty DealIDs) 146 // The committed capacity sector to replace, and it's deadline/partition location 147 ReplaceSectorDeadline uint64 148 ReplaceSectorPartition uint64 149 ReplaceSectorNumber abi.SectorNumber 150 } 151 152 // Information stored on-chain for a pre-committed sector. 153 type SectorPreCommitOnChainInfo struct { 154 Info SectorPreCommitInfo 155 PreCommitDeposit abi.TokenAmount 156 PreCommitEpoch abi.ChainEpoch 157 DealWeight abi.DealWeight // Integral of active deals over sector lifetime 158 VerifiedDealWeight abi.DealWeight // Integral of active verified deals over sector lifetime 159 } 160 161 // Information stored on-chain for a proven sector. 162 type SectorOnChainInfo struct { 163 SectorNumber abi.SectorNumber 164 SealProof abi.RegisteredSealProof // The seal proof type implies the PoSt proof/s 165 SealedCID cid.Cid // CommR 166 DealIDs []abi.DealID 167 Activation abi.ChainEpoch // Epoch during which the sector proof was accepted 168 Expiration abi.ChainEpoch // Epoch during which the sector expires 169 DealWeight abi.DealWeight // Integral of active deals over sector lifetime 170 VerifiedDealWeight abi.DealWeight // Integral of active verified deals over sector lifetime 171 InitialPledge abi.TokenAmount // Pledge collected to commit this sector 172 ExpectedDayReward abi.TokenAmount // Expected one day projection of reward for sector computed at activation time 173 ExpectedStoragePledge abi.TokenAmount // Expected twenty day projection of reward for sector computed at activation time 174 ReplacedSectorAge abi.ChainEpoch // Age of sector this sector replaced or zero 175 ReplacedDayReward abi.TokenAmount // Day reward of sector this sector replace or zero 176 } 177 178 func ConstructState(store adt.Store, infoCid cid.Cid, periodStart abi.ChainEpoch, deadlineIndex uint64) (*State, error) { 179 emptyPrecommitMapCid, err := adt.StoreEmptyMap(store, builtin.DefaultHamtBitwidth) 180 if err != nil { 181 return nil, xerrors.Errorf("failed to construct empty map: %w", err) 182 } 183 emptyPrecommitsExpiryArrayCid, err := adt.StoreEmptyArray(store, PrecommitExpiryAmtBitwidth) 184 if err != nil { 185 return nil, xerrors.Errorf("failed to construct empty precommits array: %w", err) 186 } 187 emptySectorsArrayCid, err := adt.StoreEmptyArray(store, SectorsAmtBitwidth) 188 if err != nil { 189 return nil, xerrors.Errorf("failed to construct empty sectors array: %w", err) 190 } 191 192 emptyBitfield := bitfield.NewFromSet(nil) 193 emptyBitfieldCid, err := store.Put(store.Context(), emptyBitfield) 194 if err != nil { 195 return nil, xerrors.Errorf("failed to construct empty bitfield: %w", err) 196 } 197 emptyDeadline, err := ConstructDeadline(store) 198 if err != nil { 199 return nil, xerrors.Errorf("failed to construct empty deadline: %w", err) 200 } 201 emptyDeadlineCid, err := store.Put(store.Context(), emptyDeadline) 202 if err != nil { 203 return nil, xerrors.Errorf("failed to construct empty deadline: %w", err) 204 } 205 emptyDeadlines := ConstructDeadlines(emptyDeadlineCid) 206 emptyDeadlinesCid, err := store.Put(store.Context(), emptyDeadlines) 207 if err != nil { 208 return nil, xerrors.Errorf("failed to construct empty deadlines: %w", err) 209 } 210 emptyVestingFundsCid, err := store.Put(store.Context(), ConstructVestingFunds()) 211 if err != nil { 212 return nil, xerrors.Errorf("failed to construct empty vesting funds: %w", err) 213 } 214 215 return &State{ 216 Info: infoCid, 217 218 PreCommitDeposits: abi.NewTokenAmount(0), 219 LockedFunds: abi.NewTokenAmount(0), 220 FeeDebt: abi.NewTokenAmount(0), 221 222 VestingFunds: emptyVestingFundsCid, 223 224 InitialPledge: abi.NewTokenAmount(0), 225 226 PreCommittedSectors: emptyPrecommitMapCid, 227 PreCommittedSectorsExpiry: emptyPrecommitsExpiryArrayCid, 228 AllocatedSectors: emptyBitfieldCid, 229 Sectors: emptySectorsArrayCid, 230 ProvingPeriodStart: periodStart, 231 CurrentDeadline: deadlineIndex, 232 Deadlines: emptyDeadlinesCid, 233 EarlyTerminations: bitfield.New(), 234 DeadlineCronActive: false, 235 }, nil 236 } 237 238 func ConstructMinerInfo(owner, worker addr.Address, controlAddrs []addr.Address, pid []byte, multiAddrs [][]byte, 239 windowPoStProofType abi.RegisteredPoStProof) (*MinerInfo, error) { 240 sectorSize, err := windowPoStProofType.SectorSize() 241 if err != nil { 242 return nil, xc.ErrIllegalArgument.Wrapf("invalid sector size: %w", err) 243 } 244 245 partitionSectors, err := builtin.PoStProofWindowPoStPartitionSectors(windowPoStProofType) 246 if err != nil { 247 return nil, xc.ErrIllegalArgument.Wrapf("invalid partition sectors: %w", err) 248 } 249 250 return &MinerInfo{ 251 Owner: owner, 252 Worker: worker, 253 ControlAddresses: controlAddrs, 254 PendingWorkerKey: nil, 255 PeerId: pid, 256 Multiaddrs: multiAddrs, 257 WindowPoStProofType: windowPoStProofType, 258 SectorSize: sectorSize, 259 WindowPoStPartitionSectors: partitionSectors, 260 ConsensusFaultElapsed: abi.ChainEpoch(-1), 261 PendingOwnerAddress: nil, 262 }, nil 263 } 264 265 func (st *State) GetInfo(store adt.Store) (*MinerInfo, error) { 266 var info MinerInfo 267 if err := store.Get(store.Context(), st.Info, &info); err != nil { 268 return nil, xerrors.Errorf("failed to get miner info %w", err) 269 } 270 return &info, nil 271 } 272 273 func (st *State) SaveInfo(store adt.Store, info *MinerInfo) error { 274 c, err := store.Put(store.Context(), info) 275 if err != nil { 276 return err 277 } 278 st.Info = c 279 return nil 280 } 281 282 // Returns deadline calculations for the current proving period, according to the current epoch and constant state offset 283 func (st *State) DeadlineInfo(currEpoch abi.ChainEpoch) *dline.Info { 284 return NewDeadlineInfoFromOffsetAndEpoch(st.ProvingPeriodStart, currEpoch) 285 } 286 287 // Returns deadline calculations for the state recorded proving period and deadline. This is out of date if the a 288 // miner does not have an active miner cron 289 func (st *State) RecordedDeadlineInfo(currEpoch abi.ChainEpoch) *dline.Info { 290 return NewDeadlineInfo(st.ProvingPeriodStart, st.CurrentDeadline, currEpoch) 291 } 292 293 // Returns current proving period start for the current epoch according to the current epoch and constant state offset 294 func (st *State) CurrentProvingPeriodStart(currEpoch abi.ChainEpoch) abi.ChainEpoch { 295 dlInfo := st.DeadlineInfo(currEpoch) 296 return dlInfo.PeriodStart 297 } 298 299 // Returns deadline calculations for the current (according to state) proving period 300 func (st *State) QuantSpecForDeadline(dlIdx uint64) QuantSpec { 301 return QuantSpecForDeadline(NewDeadlineInfo(st.ProvingPeriodStart, dlIdx, 0)) 302 } 303 304 func (st *State) AllocateSectorNumber(store adt.Store, sectorNo abi.SectorNumber) error { 305 // This will likely already have been checked, but this is a good place 306 // to catch any mistakes. 307 if sectorNo > abi.MaxSectorNumber { 308 return xc.ErrIllegalArgument.Wrapf("sector number out of range: %d", sectorNo) 309 } 310 311 var allocatedSectors bitfield.BitField 312 if err := store.Get(store.Context(), st.AllocatedSectors, &allocatedSectors); err != nil { 313 return xc.ErrIllegalState.Wrapf("failed to load allocated sectors bitfield: %w", err) 314 } 315 if allocated, err := allocatedSectors.IsSet(uint64(sectorNo)); err != nil { 316 return xc.ErrIllegalState.Wrapf("failed to lookup sector number in allocated sectors bitfield: %w", err) 317 } else if allocated { 318 return xc.ErrIllegalArgument.Wrapf("sector number %d has already been allocated", sectorNo) 319 } 320 allocatedSectors.Set(uint64(sectorNo)) 321 322 if root, err := store.Put(store.Context(), allocatedSectors); err != nil { 323 return xc.ErrIllegalArgument.Wrapf("failed to store allocated sectors bitfield after adding sector %d: %w", sectorNo, err) 324 } else { 325 st.AllocatedSectors = root 326 } 327 return nil 328 } 329 330 func (st *State) MaskSectorNumbers(store adt.Store, sectorNos bitfield.BitField) error { 331 lastSectorNo, err := sectorNos.Last() 332 if err != nil { 333 return xc.ErrIllegalArgument.Wrapf("invalid mask bitfield: %w", err) 334 } 335 336 if lastSectorNo > abi.MaxSectorNumber { 337 return xc.ErrIllegalArgument.Wrapf("masked sector number %d exceeded max sector number", lastSectorNo) 338 } 339 340 var allocatedSectors bitfield.BitField 341 if err := store.Get(store.Context(), st.AllocatedSectors, &allocatedSectors); err != nil { 342 return xc.ErrIllegalState.Wrapf("failed to load allocated sectors bitfield: %w", err) 343 } 344 345 allocatedSectors, err = bitfield.MergeBitFields(allocatedSectors, sectorNos) 346 if err != nil { 347 return xc.ErrIllegalState.Wrapf("failed to merge allocated bitfield with mask: %w", err) 348 } 349 350 if root, err := store.Put(store.Context(), allocatedSectors); err != nil { 351 return xc.ErrIllegalArgument.Wrapf("failed to mask allocated sectors bitfield: %w", err) 352 } else { 353 st.AllocatedSectors = root 354 } 355 return nil 356 } 357 358 // Stores a pre-committed sector info, failing if the sector number is already present. 359 func (st *State) PutPrecommittedSector(store adt.Store, info *SectorPreCommitOnChainInfo) error { 360 precommitted, err := adt.AsMap(store, st.PreCommittedSectors, builtin.DefaultHamtBitwidth) 361 if err != nil { 362 return err 363 } 364 365 if modified, err := precommitted.PutIfAbsent(SectorKey(info.Info.SectorNumber), info); err != nil { 366 return errors.Wrapf(err, "failed to store pre-commitment for %v", info) 367 } else if !modified { 368 return xerrors.Errorf("sector %v already pre-committed", info.Info.SectorNumber) 369 } 370 st.PreCommittedSectors, err = precommitted.Root() 371 return err 372 } 373 374 func (st *State) GetPrecommittedSector(store adt.Store, sectorNo abi.SectorNumber) (*SectorPreCommitOnChainInfo, bool, error) { 375 precommitted, err := adt.AsMap(store, st.PreCommittedSectors, builtin.DefaultHamtBitwidth) 376 if err != nil { 377 return nil, false, err 378 } 379 380 var info SectorPreCommitOnChainInfo 381 found, err := precommitted.Get(SectorKey(sectorNo), &info) 382 if err != nil { 383 return nil, false, errors.Wrapf(err, "failed to load precommitment for %v", sectorNo) 384 } 385 return &info, found, nil 386 } 387 388 // This method gets and returns the requested pre-committed sectors, skipping 389 // missing sectors. 390 func (st *State) FindPrecommittedSectors(store adt.Store, sectorNos ...abi.SectorNumber) ([]*SectorPreCommitOnChainInfo, error) { 391 precommitted, err := adt.AsMap(store, st.PreCommittedSectors, builtin.DefaultHamtBitwidth) 392 if err != nil { 393 return nil, err 394 } 395 396 result := make([]*SectorPreCommitOnChainInfo, 0, len(sectorNos)) 397 398 for _, sectorNo := range sectorNos { 399 var info SectorPreCommitOnChainInfo 400 found, err := precommitted.Get(SectorKey(sectorNo), &info) 401 if err != nil { 402 return nil, errors.Wrapf(err, "failed to load precommitment for %v", sectorNo) 403 } 404 if !found { 405 // TODO #564 log: "failed to get precommitted sector on sector %d, dropping from prove commit set" 406 continue 407 } 408 result = append(result, &info) 409 } 410 411 return result, nil 412 } 413 414 func (st *State) DeletePrecommittedSectors(store adt.Store, sectorNos ...abi.SectorNumber) error { 415 precommitted, err := adt.AsMap(store, st.PreCommittedSectors, builtin.DefaultHamtBitwidth) 416 if err != nil { 417 return err 418 } 419 420 for _, sectorNo := range sectorNos { 421 err = precommitted.Delete(SectorKey(sectorNo)) 422 if err != nil { 423 return xerrors.Errorf("failed to delete precommitment for %v: %w", sectorNo, err) 424 } 425 } 426 st.PreCommittedSectors, err = precommitted.Root() 427 return err 428 } 429 430 func (st *State) HasSectorNo(store adt.Store, sectorNo abi.SectorNumber) (bool, error) { 431 sectors, err := LoadSectors(store, st.Sectors) 432 if err != nil { 433 return false, err 434 } 435 436 _, found, err := sectors.Get(sectorNo) 437 if err != nil { 438 return false, xerrors.Errorf("failed to get sector %v: %w", sectorNo, err) 439 } 440 return found, nil 441 } 442 443 func (st *State) PutSectors(store adt.Store, newSectors ...*SectorOnChainInfo) error { 444 sectors, err := LoadSectors(store, st.Sectors) 445 if err != nil { 446 return xerrors.Errorf("failed to load sectors: %w", err) 447 } 448 449 err = sectors.Store(newSectors...) 450 if err != nil { 451 return err 452 } 453 454 st.Sectors, err = sectors.Root() 455 if err != nil { 456 return xerrors.Errorf("failed to persist sectors: %w", err) 457 } 458 return nil 459 } 460 461 func (st *State) GetSector(store adt.Store, sectorNo abi.SectorNumber) (*SectorOnChainInfo, bool, error) { 462 sectors, err := LoadSectors(store, st.Sectors) 463 if err != nil { 464 return nil, false, err 465 } 466 467 return sectors.Get(sectorNo) 468 } 469 470 func (st *State) DeleteSectors(store adt.Store, sectorNos bitfield.BitField) error { 471 sectors, err := LoadSectors(store, st.Sectors) 472 if err != nil { 473 return err 474 } 475 err = sectorNos.ForEach(func(sectorNo uint64) error { 476 if err = sectors.Delete(sectorNo); err != nil { 477 return xerrors.Errorf("failed to delete sector %v: %w", sectorNos, err) 478 } 479 return nil 480 }) 481 if err != nil { 482 return err 483 } 484 485 st.Sectors, err = sectors.Root() 486 return err 487 } 488 489 // Iterates sectors. 490 // The pointer provided to the callback is not safe for re-use. Copy the pointed-to value in full to hold a reference. 491 func (st *State) ForEachSector(store adt.Store, f func(*SectorOnChainInfo)) error { 492 sectors, err := LoadSectors(store, st.Sectors) 493 if err != nil { 494 return err 495 } 496 var sector SectorOnChainInfo 497 return sectors.ForEach(§or, func(idx int64) error { 498 f(§or) 499 return nil 500 }) 501 } 502 503 func (st *State) FindSector(store adt.Store, sno abi.SectorNumber) (uint64, uint64, error) { 504 deadlines, err := st.LoadDeadlines(store) 505 if err != nil { 506 return 0, 0, err 507 } 508 return FindSector(store, deadlines, sno) 509 } 510 511 // Schedules each sector to expire at its next deadline end. If it can't find 512 // any given sector, it skips it. 513 // 514 // This method assumes that each sector's power has not changed, despite the rescheduling. 515 // 516 // Note: this method is used to "upgrade" sectors, rescheduling the now-replaced 517 // sectors to expire at the end of the next deadline. Given the expense of 518 // sealing a sector, this function skips missing/faulty/terminated "upgraded" 519 // sectors instead of failing. That way, the new sectors can still be proved. 520 func (st *State) RescheduleSectorExpirations( 521 store adt.Store, currEpoch abi.ChainEpoch, ssize abi.SectorSize, 522 deadlineSectors DeadlineSectorMap, 523 ) ([]*SectorOnChainInfo, error) { 524 deadlines, err := st.LoadDeadlines(store) 525 if err != nil { 526 return nil, err 527 } 528 sectors, err := LoadSectors(store, st.Sectors) 529 if err != nil { 530 return nil, err 531 } 532 533 var allReplaced []*SectorOnChainInfo 534 if err = deadlineSectors.ForEach(func(dlIdx uint64, pm PartitionSectorMap) error { 535 dlInfo := NewDeadlineInfo(st.CurrentProvingPeriodStart(currEpoch), dlIdx, currEpoch).NextNotElapsed() 536 newExpiration := dlInfo.Last() 537 538 dl, err := deadlines.LoadDeadline(store, dlIdx) 539 if err != nil { 540 return err 541 } 542 543 replaced, err := dl.RescheduleSectorExpirations(store, sectors, newExpiration, pm, ssize, QuantSpecForDeadline(dlInfo)) 544 if err != nil { 545 return err 546 } 547 allReplaced = append(allReplaced, replaced...) 548 549 if err := deadlines.UpdateDeadline(store, dlIdx, dl); err != nil { 550 return err 551 } 552 553 return nil 554 }); err != nil { 555 return nil, err 556 } 557 return allReplaced, st.SaveDeadlines(store, deadlines) 558 } 559 560 // Assign new sectors to deadlines. 561 func (st *State) AssignSectorsToDeadlines( 562 store adt.Store, currentEpoch abi.ChainEpoch, sectors []*SectorOnChainInfo, partitionSize uint64, sectorSize abi.SectorSize, 563 ) error { 564 deadlines, err := st.LoadDeadlines(store) 565 if err != nil { 566 return err 567 } 568 569 // Sort sectors by number to get better runs in partition bitfields. 570 sort.Slice(sectors, func(i, j int) bool { 571 return sectors[i].SectorNumber < sectors[j].SectorNumber 572 }) 573 574 var deadlineArr [WPoStPeriodDeadlines]*Deadline 575 if err = deadlines.ForEach(store, func(idx uint64, dl *Deadline) error { 576 // Skip deadlines that aren't currently mutable. 577 if deadlineIsMutable(st.CurrentProvingPeriodStart(currentEpoch), idx, currentEpoch) { 578 deadlineArr[int(idx)] = dl 579 } 580 return nil 581 }); err != nil { 582 return err 583 } 584 585 deadlineToSectors, err := assignDeadlines(MaxPartitionsPerDeadline, partitionSize, &deadlineArr, sectors) 586 if err != nil { 587 return xerrors.Errorf("failed to assign sectors to deadlines: %w", err) 588 } 589 590 for dlIdx, deadlineSectors := range deadlineToSectors { 591 if len(deadlineSectors) == 0 { 592 continue 593 } 594 595 quant := st.QuantSpecForDeadline(uint64(dlIdx)) 596 dl := deadlineArr[dlIdx] 597 598 // The power returned from AddSectors is ignored because it's not activated (proven) yet. 599 proven := false 600 if _, err := dl.AddSectors(store, partitionSize, proven, deadlineSectors, sectorSize, quant); err != nil { 601 return err 602 } 603 604 if err := deadlines.UpdateDeadline(store, uint64(dlIdx), dl); err != nil { 605 return err 606 } 607 } 608 609 if err := st.SaveDeadlines(store, deadlines); err != nil { 610 return err 611 } 612 return nil 613 } 614 615 // Pops up to max early terminated sectors from all deadlines. 616 // 617 // Returns hasMore if we still have more early terminations to process. 618 func (st *State) PopEarlyTerminations(store adt.Store, maxPartitions, maxSectors uint64) (result TerminationResult, hasMore bool, err error) { 619 stopErr := errors.New("stop error") 620 621 // Anything to do? This lets us avoid loading the deadlines if there's nothing to do. 622 noEarlyTerminations, err := st.EarlyTerminations.IsEmpty() 623 if err != nil { 624 return TerminationResult{}, false, xerrors.Errorf("failed to count deadlines with early terminations: %w", err) 625 } else if noEarlyTerminations { 626 return TerminationResult{}, false, nil 627 } 628 629 // Load deadlines 630 deadlines, err := st.LoadDeadlines(store) 631 if err != nil { 632 return TerminationResult{}, false, xerrors.Errorf("failed to load deadlines: %w", err) 633 } 634 635 // Process early terminations. 636 if err = st.EarlyTerminations.ForEach(func(dlIdx uint64) error { 637 // Load deadline + partitions. 638 dl, err := deadlines.LoadDeadline(store, dlIdx) 639 if err != nil { 640 return xerrors.Errorf("failed to load deadline %d: %w", dlIdx, err) 641 } 642 643 deadlineResult, more, err := dl.PopEarlyTerminations(store, maxPartitions-result.PartitionsProcessed, maxSectors-result.SectorsProcessed) 644 if err != nil { 645 return xerrors.Errorf("failed to pop early terminations for deadline %d: %w", dlIdx, err) 646 } 647 648 err = result.Add(deadlineResult) 649 if err != nil { 650 return xerrors.Errorf("failed to merge result from popping early terminations from deadline: %w", err) 651 } 652 653 if !more { 654 // safe to do while iterating. 655 st.EarlyTerminations.Unset(dlIdx) 656 } 657 658 // Save the deadline 659 err = deadlines.UpdateDeadline(store, dlIdx, dl) 660 if err != nil { 661 return xerrors.Errorf("failed to store deadline %d: %w", dlIdx, err) 662 } 663 664 if result.BelowLimit(maxPartitions, maxSectors) { 665 return nil 666 } 667 668 return stopErr 669 }); err != nil && err != stopErr { 670 return TerminationResult{}, false, xerrors.Errorf("failed to walk early terminations bitfield for deadlines: %w", err) 671 } 672 673 // Save back the deadlines. 674 err = st.SaveDeadlines(store, deadlines) 675 if err != nil { 676 return TerminationResult{}, false, xerrors.Errorf("failed to save deadlines: %w", err) 677 } 678 679 // Ok, check to see if we've handled all early terminations. 680 noEarlyTerminations, err = st.EarlyTerminations.IsEmpty() 681 if err != nil { 682 return TerminationResult{}, false, xerrors.Errorf("failed to count remaining early terminations deadlines") 683 } 684 685 return result, !noEarlyTerminations, nil 686 } 687 688 // Returns an error if the target sector cannot be found and/or is faulty/terminated. 689 func (st *State) CheckSectorHealth(store adt.Store, dlIdx, pIdx uint64, sector abi.SectorNumber) error { 690 dls, err := st.LoadDeadlines(store) 691 if err != nil { 692 return err 693 } 694 695 dl, err := dls.LoadDeadline(store, dlIdx) 696 if err != nil { 697 return err 698 } 699 700 partition, err := dl.LoadPartition(store, pIdx) 701 if err != nil { 702 return err 703 } 704 705 if exists, err := partition.Sectors.IsSet(uint64(sector)); err != nil { 706 return xc.ErrIllegalState.Wrapf("failed to decode sectors bitfield (deadline %d, partition %d): %w", dlIdx, pIdx, err) 707 } else if !exists { 708 return xc.ErrNotFound.Wrapf("sector %d not a member of partition %d, deadline %d", sector, pIdx, dlIdx) 709 } 710 711 if faulty, err := partition.Faults.IsSet(uint64(sector)); err != nil { 712 return xc.ErrIllegalState.Wrapf("failed to decode faults bitfield (deadline %d, partition %d): %w", dlIdx, pIdx, err) 713 } else if faulty { 714 return xc.ErrForbidden.Wrapf("sector %d of partition %d, deadline %d is faulty", sector, pIdx, dlIdx) 715 } 716 717 if terminated, err := partition.Terminated.IsSet(uint64(sector)); err != nil { 718 return xc.ErrIllegalState.Wrapf("failed to decode terminated bitfield (deadline %d, partition %d): %w", dlIdx, pIdx, err) 719 } else if terminated { 720 return xc.ErrNotFound.Wrapf("sector %d of partition %d, deadline %d is terminated", sector, pIdx, dlIdx) 721 } 722 723 return nil 724 } 725 726 // Loads sector info for a sequence of sectors. 727 func (st *State) LoadSectorInfos(store adt.Store, sectors bitfield.BitField) ([]*SectorOnChainInfo, error) { 728 sectorsArr, err := LoadSectors(store, st.Sectors) 729 if err != nil { 730 return nil, err 731 } 732 return sectorsArr.Load(sectors) 733 } 734 735 func (st *State) LoadDeadlines(store adt.Store) (*Deadlines, error) { 736 var deadlines Deadlines 737 if err := store.Get(store.Context(), st.Deadlines, &deadlines); err != nil { 738 return nil, xc.ErrIllegalState.Wrapf("failed to load deadlines (%s): %w", st.Deadlines, err) 739 } 740 741 return &deadlines, nil 742 } 743 744 func (st *State) SaveDeadlines(store adt.Store, deadlines *Deadlines) error { 745 c, err := store.Put(store.Context(), deadlines) 746 if err != nil { 747 return err 748 } 749 st.Deadlines = c 750 return nil 751 } 752 753 // LoadVestingFunds loads the vesting funds table from the store 754 func (st *State) LoadVestingFunds(store adt.Store) (*VestingFunds, error) { 755 var funds VestingFunds 756 if err := store.Get(store.Context(), st.VestingFunds, &funds); err != nil { 757 return nil, xerrors.Errorf("failed to load vesting funds (%s): %w", st.VestingFunds, err) 758 } 759 760 return &funds, nil 761 } 762 763 // SaveVestingFunds saves the vesting table to the store 764 func (st *State) SaveVestingFunds(store adt.Store, funds *VestingFunds) error { 765 c, err := store.Put(store.Context(), funds) 766 if err != nil { 767 return err 768 } 769 st.VestingFunds = c 770 return nil 771 } 772 773 // Return true when the miner actor needs to continue scheduling deadline crons 774 func (st *State) ContinueDeadlineCron() bool { 775 return !st.PreCommitDeposits.IsZero() || 776 !st.InitialPledge.IsZero() || 777 !st.LockedFunds.IsZero() 778 } 779 780 // 781 // Funds and vesting 782 // 783 784 func (st *State) AddPreCommitDeposit(amount abi.TokenAmount) error { 785 newTotal := big.Add(st.PreCommitDeposits, amount) 786 if newTotal.LessThan(big.Zero()) { 787 return xerrors.Errorf("negative pre-commit deposit %v after adding %v to prior %v", newTotal, amount, st.PreCommitDeposits) 788 } 789 st.PreCommitDeposits = newTotal 790 return nil 791 } 792 793 func (st *State) AddInitialPledge(amount abi.TokenAmount) error { 794 newTotal := big.Add(st.InitialPledge, amount) 795 if newTotal.LessThan(big.Zero()) { 796 return xerrors.Errorf("negative initial pledge %v after adding %v to prior %v", newTotal, amount, st.InitialPledge) 797 } 798 st.InitialPledge = newTotal 799 return nil 800 } 801 802 // AddLockedFunds first vests and unlocks the vested funds AND then locks the given funds in the vesting table. 803 func (st *State) AddLockedFunds(store adt.Store, currEpoch abi.ChainEpoch, vestingSum abi.TokenAmount, spec *VestSpec) (vested abi.TokenAmount, err error) { 804 if vestingSum.LessThan(big.Zero()) { 805 return big.Zero(), xerrors.Errorf("negative amount to lock %s", vestingSum) 806 } 807 808 vestingFunds, err := st.LoadVestingFunds(store) 809 if err != nil { 810 return big.Zero(), xerrors.Errorf("failed to load vesting funds: %w", err) 811 } 812 813 // unlock vested funds first 814 amountUnlocked := vestingFunds.unlockVestedFunds(currEpoch) 815 st.LockedFunds = big.Sub(st.LockedFunds, amountUnlocked) 816 if st.LockedFunds.LessThan(big.Zero()) { 817 return big.Zero(), xerrors.Errorf("negative locked funds %v after unlocking %v", st.LockedFunds, amountUnlocked) 818 } 819 820 // add locked funds now 821 vestingFunds.addLockedFunds(currEpoch, vestingSum, st.ProvingPeriodStart, spec) 822 st.LockedFunds = big.Add(st.LockedFunds, vestingSum) 823 824 // save the updated vesting table state 825 if err := st.SaveVestingFunds(store, vestingFunds); err != nil { 826 return big.Zero(), xerrors.Errorf("failed to save vesting funds: %w", err) 827 } 828 829 return amountUnlocked, nil 830 } 831 832 // ApplyPenalty adds the provided penalty to fee debt. 833 func (st *State) ApplyPenalty(penalty abi.TokenAmount) error { 834 if penalty.LessThan(big.Zero()) { 835 return xerrors.Errorf("applying negative penalty %v not allowed", penalty) 836 } 837 st.FeeDebt = big.Add(st.FeeDebt, penalty) 838 return nil 839 } 840 841 // Draws from vesting table and unlocked funds to repay up to the fee debt. 842 // Returns the amount unlocked from the vesting table and the amount taken from 843 // current balance. If the fee debt exceeds the total amount available for repayment 844 // the fee debt field is updated to track the remaining debt. Otherwise it is set to zero. 845 func (st *State) RepayPartialDebtInPriorityOrder(store adt.Store, currEpoch abi.ChainEpoch, currBalance abi.TokenAmount) (fromVesting abi.TokenAmount, fromBalance abi.TokenAmount, err error) { 846 unlockedBalance, err := st.GetUnlockedBalance(currBalance) 847 if err != nil { 848 return big.Zero(), big.Zero(), err 849 } 850 851 // Pay fee debt with locked funds first 852 fromVesting, err = st.UnlockUnvestedFunds(store, currEpoch, st.FeeDebt) 853 if err != nil { 854 return abi.NewTokenAmount(0), abi.NewTokenAmount(0), err 855 } 856 857 // We should never unlock more than the debt we need to repay 858 if fromVesting.GreaterThan(st.FeeDebt) { 859 return big.Zero(), big.Zero(), xerrors.Errorf("unlocked more vesting funds %v than required for debt %v", fromVesting, st.FeeDebt) 860 } 861 st.FeeDebt = big.Sub(st.FeeDebt, fromVesting) 862 863 fromBalance = big.Min(unlockedBalance, st.FeeDebt) 864 st.FeeDebt = big.Sub(st.FeeDebt, fromBalance) 865 866 return fromVesting, fromBalance, nil 867 868 } 869 870 // Repays the full miner actor fee debt. Returns the amount that must be 871 // burnt and an error if there are not sufficient funds to cover repayment. 872 // Miner state repays from unlocked funds and fails if unlocked funds are insufficient to cover fee debt. 873 // FeeDebt will be zero after a successful call. 874 func (st *State) repayDebts(currBalance abi.TokenAmount) (abi.TokenAmount, error) { 875 unlockedBalance, err := st.GetUnlockedBalance(currBalance) 876 if err != nil { 877 return big.Zero(), err 878 } 879 if unlockedBalance.LessThan(st.FeeDebt) { 880 return big.Zero(), xc.ErrInsufficientFunds.Wrapf("unlocked balance can not repay fee debt (%v < %v)", unlockedBalance, st.FeeDebt) 881 } 882 debtToRepay := st.FeeDebt 883 st.FeeDebt = big.Zero() 884 return debtToRepay, nil 885 } 886 887 // Unlocks an amount of funds that have *not yet vested*, if possible. 888 // The soonest-vesting entries are unlocked first. 889 // Returns the amount actually unlocked. 890 func (st *State) UnlockUnvestedFunds(store adt.Store, currEpoch abi.ChainEpoch, target abi.TokenAmount) (abi.TokenAmount, error) { 891 // Nothing to unlock, don't bother loading any state. 892 if target.IsZero() || st.LockedFunds.IsZero() { 893 return big.Zero(), nil 894 } 895 896 vestingFunds, err := st.LoadVestingFunds(store) 897 if err != nil { 898 return big.Zero(), xerrors.Errorf("failed tp load vesting funds: %w", err) 899 } 900 901 amountUnlocked := vestingFunds.unlockUnvestedFunds(currEpoch, target) 902 903 st.LockedFunds = big.Sub(st.LockedFunds, amountUnlocked) 904 if st.LockedFunds.LessThan(big.Zero()) { 905 return big.Zero(), xerrors.Errorf("negative locked funds %v after unlocking %v", st.LockedFunds, amountUnlocked) 906 } 907 908 if err := st.SaveVestingFunds(store, vestingFunds); err != nil { 909 return big.Zero(), xerrors.Errorf("failed to save vesting funds: %w", err) 910 } 911 912 return amountUnlocked, nil 913 } 914 915 // Unlocks all vesting funds that have vested before the provided epoch. 916 // Returns the amount unlocked. 917 func (st *State) UnlockVestedFunds(store adt.Store, currEpoch abi.ChainEpoch) (abi.TokenAmount, error) { 918 // Short-circuit to avoid loading vesting funds if we don't have any. 919 if st.LockedFunds.IsZero() { 920 return big.Zero(), nil 921 } 922 923 vestingFunds, err := st.LoadVestingFunds(store) 924 if err != nil { 925 return big.Zero(), xerrors.Errorf("failed to load vesting funds: %w", err) 926 } 927 928 amountUnlocked := vestingFunds.unlockVestedFunds(currEpoch) 929 st.LockedFunds = big.Sub(st.LockedFunds, amountUnlocked) 930 if st.LockedFunds.LessThan(big.Zero()) { 931 return big.Zero(), xerrors.Errorf("vesting cause locked funds negative %v", st.LockedFunds) 932 } 933 934 err = st.SaveVestingFunds(store, vestingFunds) 935 if err != nil { 936 return big.Zero(), xerrors.Errorf("failed to save vesing funds: %w", err) 937 } 938 939 return amountUnlocked, nil 940 } 941 942 // CheckVestedFunds returns the amount of vested funds that have vested before the provided epoch. 943 func (st *State) CheckVestedFunds(store adt.Store, currEpoch abi.ChainEpoch) (abi.TokenAmount, error) { 944 vestingFunds, err := st.LoadVestingFunds(store) 945 if err != nil { 946 return big.Zero(), xerrors.Errorf("failed to load vesting funds: %w", err) 947 } 948 949 amountVested := abi.NewTokenAmount(0) 950 951 for i := range vestingFunds.Funds { 952 vf := vestingFunds.Funds[i] 953 epoch := vf.Epoch 954 amount := vf.Amount 955 956 if epoch >= currEpoch { 957 break 958 } 959 960 amountVested = big.Add(amountVested, amount) 961 } 962 963 return amountVested, nil 964 } 965 966 // Unclaimed funds that are not locked -- includes free funds and does not 967 // account for fee debt. Always greater than or equal to zero 968 func (st *State) GetUnlockedBalance(actorBalance abi.TokenAmount) (abi.TokenAmount, error) { 969 unlockedBalance := big.Subtract(actorBalance, st.LockedFunds, st.PreCommitDeposits, st.InitialPledge) 970 if unlockedBalance.LessThan(big.Zero()) { 971 return big.Zero(), xerrors.Errorf("negative unlocked balance %v", unlockedBalance) 972 } 973 return unlockedBalance, nil 974 } 975 976 // Unclaimed funds. Actor balance - (locked funds, precommit deposit, initial pledge, fee debt) 977 // Can go negative if the miner is in IP debt 978 func (st *State) GetAvailableBalance(actorBalance abi.TokenAmount) (abi.TokenAmount, error) { 979 unlockedBalance, err := st.GetUnlockedBalance(actorBalance) 980 if err != nil { 981 return big.Zero(), err 982 } 983 return big.Subtract(unlockedBalance, st.FeeDebt), nil 984 } 985 986 func (st *State) CheckBalanceInvariants(balance abi.TokenAmount) error { 987 if st.PreCommitDeposits.LessThan(big.Zero()) { 988 return xerrors.Errorf("pre-commit deposit is negative: %v", st.PreCommitDeposits) 989 } 990 if st.LockedFunds.LessThan(big.Zero()) { 991 return xerrors.Errorf("locked funds is negative: %v", st.LockedFunds) 992 } 993 if st.InitialPledge.LessThan(big.Zero()) { 994 return xerrors.Errorf("initial pledge is negative: %v", st.InitialPledge) 995 } 996 if st.FeeDebt.LessThan(big.Zero()) { 997 return xerrors.Errorf("fee debt is negative: %v", st.InitialPledge) 998 } 999 minBalance := big.Sum(st.PreCommitDeposits, st.LockedFunds, st.InitialPledge) 1000 if balance.LessThan(minBalance) { 1001 return xerrors.Errorf("balance %v below required %v", balance, minBalance) 1002 } 1003 return nil 1004 } 1005 1006 func (st *State) IsDebtFree() bool { 1007 return st.FeeDebt.LessThanEqual(big.Zero()) 1008 } 1009 1010 // pre-commit expiry 1011 func (st *State) QuantSpecEveryDeadline() QuantSpec { 1012 return NewQuantSpec(WPoStChallengeWindow, st.ProvingPeriodStart) 1013 } 1014 1015 func (st *State) AddPreCommitExpiry(store adt.Store, expireEpoch abi.ChainEpoch, sectorNum abi.SectorNumber) error { 1016 // Load BitField Queue for sector expiry 1017 quant := st.QuantSpecEveryDeadline() 1018 queue, err := LoadBitfieldQueue(store, st.PreCommittedSectorsExpiry, quant, PrecommitExpiryAmtBitwidth) 1019 if err != nil { 1020 return xerrors.Errorf("failed to load pre-commit expiry queue: %w", err) 1021 } 1022 1023 // add entry for this sector to the queue 1024 if err := queue.AddToQueueValues(expireEpoch, uint64(sectorNum)); err != nil { 1025 return xerrors.Errorf("failed to add pre-commit sector expiry to queue: %w", err) 1026 } 1027 1028 st.PreCommittedSectorsExpiry, err = queue.Root() 1029 if err != nil { 1030 return xerrors.Errorf("failed to save pre-commit sector queue: %w", err) 1031 } 1032 1033 return nil 1034 } 1035 1036 func (st *State) ExpirePreCommits(store adt.Store, currEpoch abi.ChainEpoch) (depositToBurn abi.TokenAmount, err error) { 1037 depositToBurn = abi.NewTokenAmount(0) 1038 1039 // expire pre-committed sectors 1040 expiryQ, err := LoadBitfieldQueue(store, st.PreCommittedSectorsExpiry, st.QuantSpecEveryDeadline(), PrecommitExpiryAmtBitwidth) 1041 if err != nil { 1042 return depositToBurn, xerrors.Errorf("failed to load sector expiry queue: %w", err) 1043 } 1044 1045 sectors, modified, err := expiryQ.PopUntil(currEpoch) 1046 if err != nil { 1047 return depositToBurn, xerrors.Errorf("failed to pop expired sectors: %w", err) 1048 } 1049 1050 if modified { 1051 st.PreCommittedSectorsExpiry, err = expiryQ.Root() 1052 if err != nil { 1053 return depositToBurn, xerrors.Errorf("failed to save expiry queue: %w", err) 1054 } 1055 } 1056 1057 var precommitsToDelete []abi.SectorNumber 1058 if err = sectors.ForEach(func(i uint64) error { 1059 sectorNo := abi.SectorNumber(i) 1060 sector, found, err := st.GetPrecommittedSector(store, sectorNo) 1061 if err != nil { 1062 return err 1063 } 1064 if !found { 1065 // already committed/deleted 1066 return nil 1067 } 1068 1069 // mark it for deletion 1070 precommitsToDelete = append(precommitsToDelete, sectorNo) 1071 1072 // increment deposit to burn 1073 depositToBurn = big.Add(depositToBurn, sector.PreCommitDeposit) 1074 return nil 1075 }); err != nil { 1076 return big.Zero(), xerrors.Errorf("failed to check pre-commit expiries: %w", err) 1077 } 1078 1079 // Actually delete it. 1080 if len(precommitsToDelete) > 0 { 1081 if err := st.DeletePrecommittedSectors(store, precommitsToDelete...); err != nil { 1082 return big.Zero(), fmt.Errorf("failed to delete pre-commits: %w", err) 1083 } 1084 } 1085 1086 st.PreCommitDeposits = big.Sub(st.PreCommitDeposits, depositToBurn) 1087 if st.PreCommitDeposits.LessThan(big.Zero()) { 1088 return big.Zero(), xerrors.Errorf("pre-commit expiry caused negative deposits: %v", st.PreCommitDeposits) 1089 } 1090 1091 // This deposit was locked separately to pledge collateral so there's no pledge change here. 1092 return depositToBurn, nil 1093 } 1094 1095 type AdvanceDeadlineResult struct { 1096 PledgeDelta abi.TokenAmount 1097 PowerDelta PowerPair 1098 PreviouslyFaultyPower PowerPair // Power that was faulty before this advance (including recovering) 1099 DetectedFaultyPower PowerPair // Power of new faults and failed recoveries 1100 TotalFaultyPower PowerPair // Total faulty power after detecting faults (before expiring sectors) 1101 // Note that failed recovery power is included in both PreviouslyFaultyPower and DetectedFaultyPower, 1102 // so TotalFaultyPower is not simply their sum. 1103 } 1104 1105 // AdvanceDeadline advances the deadline. It: 1106 // - Processes expired sectors. 1107 // - Handles missed proofs. 1108 // - Returns the changes to power & pledge, and faulty power (both declared and undeclared). 1109 func (st *State) AdvanceDeadline(store adt.Store, currEpoch abi.ChainEpoch) (*AdvanceDeadlineResult, error) { 1110 pledgeDelta := abi.NewTokenAmount(0) 1111 powerDelta := NewPowerPairZero() 1112 1113 var totalFaultyPower PowerPair 1114 detectedFaultyPower := NewPowerPairZero() 1115 1116 // Note: Use dlInfo.Last() rather than rt.CurrEpoch unless certain 1117 // of the desired semantics. In the past, this method would sometimes be 1118 // invoked late due to skipped blocks. This is no longer the case, but 1119 // we still use dlInfo.Last(). 1120 dlInfo := st.DeadlineInfo(currEpoch) 1121 1122 // Return early if the proving period hasn't started. While actors v2 1123 // sets the proving period start into the past so this case can never 1124 // happen, v1: 1125 // 1126 // 1. Sets the proving period in the future. 1127 // 2. Schedules the first cron event one epoch _before_ the proving 1128 // period start. 1129 // 1130 // At this point, no proofs have been submitted so we can't check them. 1131 if !dlInfo.PeriodStarted() { 1132 return &AdvanceDeadlineResult{ 1133 pledgeDelta, 1134 powerDelta, 1135 NewPowerPairZero(), 1136 NewPowerPairZero(), 1137 NewPowerPairZero(), 1138 }, nil 1139 } 1140 1141 // Advance to the next deadline (in case we short-circuit below). 1142 // Maintaining this state info is a legacy operation no longer required for code correctness 1143 st.CurrentDeadline = (dlInfo.Index + 1) % WPoStPeriodDeadlines 1144 if st.CurrentDeadline == 0 { 1145 st.ProvingPeriodStart = dlInfo.PeriodStart + WPoStProvingPeriod 1146 } 1147 1148 deadlines, err := st.LoadDeadlines(store) 1149 if err != nil { 1150 return nil, xerrors.Errorf("failed to load deadlines: %w", err) 1151 } 1152 deadline, err := deadlines.LoadDeadline(store, dlInfo.Index) 1153 if err != nil { 1154 return nil, xerrors.Errorf("failed to load deadline %d: %w", dlInfo.Index, err) 1155 } 1156 1157 previouslyFaultyPower := deadline.FaultyPower 1158 1159 // No live sectors in this deadline, nothing to do. 1160 if live, err := deadline.IsLive(); err != nil { 1161 return nil, xerrors.Errorf("failed to determine if miner is live: %w", err) 1162 } else if !live { 1163 return &AdvanceDeadlineResult{ 1164 pledgeDelta, 1165 powerDelta, 1166 previouslyFaultyPower, 1167 detectedFaultyPower, 1168 deadline.FaultyPower, 1169 }, nil 1170 } 1171 1172 quant := QuantSpecForDeadline(dlInfo) 1173 { 1174 // Detect and penalize missing proofs. 1175 faultExpiration := dlInfo.Last() + FaultMaxAge 1176 1177 // detectedFaultyPower is new faults and failed recoveries 1178 powerDelta, detectedFaultyPower, err = deadline.ProcessDeadlineEnd(store, quant, faultExpiration) 1179 if err != nil { 1180 return nil, xerrors.Errorf("failed to process end of deadline %d: %w", dlInfo.Index, err) 1181 } 1182 1183 // Capture deadline's faulty power after new faults have been detected, but before it is 1184 // dropped along with faulty sectors expiring this round. 1185 totalFaultyPower = deadline.FaultyPower 1186 } 1187 { 1188 // Expire sectors that are due, either for on-time expiration or "early" faulty-for-too-long. 1189 expired, err := deadline.PopExpiredSectors(store, dlInfo.Last(), quant) 1190 if err != nil { 1191 return nil, xerrors.Errorf("failed to load expired sectors: %w", err) 1192 } 1193 1194 // Release pledge requirements for the sectors expiring on-time. 1195 // Pledge for the sectors expiring early is retained to support the termination fee that will be assessed 1196 // when the early termination is processed. 1197 pledgeDelta = big.Sub(pledgeDelta, expired.OnTimePledge) 1198 if err = st.AddInitialPledge(expired.OnTimePledge.Neg()); err != nil { 1199 return nil, xerrors.Errorf("failed to reduce %v initial pledge for expiring sectors: %w", expired.OnTimePledge, err) 1200 } 1201 1202 // Record reduction in power of the amount of expiring active power. 1203 // Faulty power has already been lost, so the amount expiring can be excluded from the delta. 1204 powerDelta = powerDelta.Sub(expired.ActivePower) 1205 1206 // Record deadlines with early terminations. While this 1207 // bitfield is non-empty, the miner is locked until they 1208 // pay the fee. 1209 noEarlyTerminations, err := expired.EarlySectors.IsEmpty() 1210 if err != nil { 1211 return nil, xerrors.Errorf("failed to count early terminations: %w", err) 1212 } 1213 if !noEarlyTerminations { 1214 st.EarlyTerminations.Set(dlInfo.Index) 1215 } 1216 } 1217 1218 // Save new deadline state. 1219 err = deadlines.UpdateDeadline(store, dlInfo.Index, deadline) 1220 if err != nil { 1221 return nil, xerrors.Errorf("failed to update deadline %d: %w", dlInfo.Index, err) 1222 } 1223 1224 err = st.SaveDeadlines(store, deadlines) 1225 if err != nil { 1226 return nil, xerrors.Errorf("failed to save deadlines: %w", err) 1227 } 1228 1229 // Compute penalties all together. 1230 // Be very careful when changing these as any changes can affect rounding. 1231 return &AdvanceDeadlineResult{ 1232 PledgeDelta: pledgeDelta, 1233 PowerDelta: powerDelta, 1234 PreviouslyFaultyPower: previouslyFaultyPower, 1235 DetectedFaultyPower: detectedFaultyPower, 1236 TotalFaultyPower: totalFaultyPower, 1237 }, nil 1238 } 1239 1240 // 1241 // Misc helpers 1242 // 1243 1244 func SectorKey(e abi.SectorNumber) abi.Keyer { 1245 return abi.UIntKey(uint64(e)) 1246 } 1247 1248 func init() { 1249 // Check that ChainEpoch is indeed an unsigned integer to confirm that SectorKey is making the right interpretation. 1250 var e abi.SectorNumber 1251 if reflect.TypeOf(e).Kind() != reflect.Uint64 { 1252 panic("incorrect sector number encoding") 1253 } 1254 }