github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/builtin/miner/monies.go (about)

     1  package miner
     2  
     3  import (
     4  	"github.com/filecoin-project/go-state-types/abi"
     5  	"github.com/filecoin-project/go-state-types/big"
     6  	"github.com/filecoin-project/go-state-types/exitcode"
     7  
     8  	"github.com/filecoin-project/specs-actors/v4/actors/builtin"
     9  	"github.com/filecoin-project/specs-actors/v4/actors/util/math"
    10  	"github.com/filecoin-project/specs-actors/v4/actors/util/smoothing"
    11  )
    12  
    13  // Projection period of expected sector block reward for deposit required to pre-commit a sector.
    14  // This deposit is lost if the pre-commitment is not timely followed up by a commitment proof.
    15  var PreCommitDepositFactor = 20 // PARAM_SPEC
    16  var PreCommitDepositProjectionPeriod = abi.ChainEpoch(PreCommitDepositFactor) * builtin.EpochsInDay
    17  
    18  // Projection period of expected sector block rewards for storage pledge required to commit a sector.
    19  // This pledge is lost if a sector is terminated before its full committed lifetime.
    20  var InitialPledgeFactor = 20 // PARAM_SPEC
    21  var InitialPledgeProjectionPeriod = abi.ChainEpoch(InitialPledgeFactor) * builtin.EpochsInDay
    22  
    23  // Cap on initial pledge requirement for sectors.
    24  // The target is 1 FIL (10**18 attoFIL) per 32GiB.
    25  // This does not divide evenly, so the result is fractionally smaller.
    26  var InitialPledgeMaxPerByte = big.Div(big.NewInt(1e18), big.NewInt(32<<30))
    27  
    28  // Multiplier of share of circulating money supply for consensus pledge required to commit a sector.
    29  // This pledge is lost if a sector is terminated before its full committed lifetime.
    30  var InitialPledgeLockTarget = builtin.BigFrac{
    31  	Numerator:   big.NewInt(3), // PARAM_SPEC
    32  	Denominator: big.NewInt(10),
    33  }
    34  
    35  // Projection period of expected daily sector block reward penalised when a fault is continued after initial detection.
    36  // This guarantees that a miner pays back at least the expected block reward earned since the last successful PoSt.
    37  // The network conservatively assumes the sector was faulty since the last time it was proven.
    38  // This penalty is currently overly punitive for continued faults.
    39  // FF = BR(t, ContinuedFaultProjectionPeriod)
    40  var ContinuedFaultFactorNum = 351 // PARAM_SPEC
    41  var ContinuedFaultFactorDenom = 100
    42  var ContinuedFaultProjectionPeriod = abi.ChainEpoch((builtin.EpochsInDay * ContinuedFaultFactorNum) / ContinuedFaultFactorDenom)
    43  
    44  var TerminationPenaltyLowerBoundProjectionPeriod = abi.ChainEpoch((builtin.EpochsInDay * 35) / 10) // PARAM_SPEC
    45  
    46  // FF + 2BR
    47  var InvalidWindowPoStProjectionPeriod = abi.ChainEpoch(ContinuedFaultProjectionPeriod + 2*builtin.EpochsInDay) // PARAM_SPEC
    48  
    49  // Fraction of assumed block reward penalized when a sector is terminated.
    50  var TerminationRewardFactor = builtin.BigFrac{ // PARAM_SPEC
    51  	Numerator:   big.NewInt(1),
    52  	Denominator: big.NewInt(2),
    53  }
    54  
    55  // Maximum number of lifetime days penalized when a sector is terminated.
    56  const TerminationLifetimeCap = 140 // PARAM_SPEC
    57  
    58  // Multiplier of whole per-winner rewards for a consensus fault penalty.
    59  const ConsensusFaultFactor = 5
    60  
    61  // Fraction of total reward (block reward + gas reward) to be locked up as of V6
    62  var LockedRewardFactorNum = big.NewInt(75)
    63  var LockedRewardFactorDenom = big.NewInt(100)
    64  
    65  // Base reward for successfully disputing a window posts proofs.
    66  var BaseRewardForDisputedWindowPoSt = big.Mul(big.NewInt(4), builtin.TokenPrecision) // PARAM_SPEC
    67  // Base penalty for a successful disputed window post proof.
    68  var BasePenaltyForDisputedWindowPoSt = big.Mul(big.NewInt(20), builtin.TokenPrecision) // PARAM_SPEC
    69  
    70  // The projected block reward a sector would earn over some period.
    71  // Also known as "BR(t)".
    72  // BR(t) = ProjectedRewardFraction(t) * SectorQualityAdjustedPower
    73  // ProjectedRewardFraction(t) is the sum of estimated reward over estimated total power
    74  // over all epochs in the projection period [t t+projectionDuration]
    75  func ExpectedRewardForPower(rewardEstimate, networkQAPowerEstimate smoothing.FilterEstimate, qaSectorPower abi.StoragePower, projectionDuration abi.ChainEpoch) abi.TokenAmount {
    76  	networkQAPowerSmoothed := networkQAPowerEstimate.Estimate()
    77  	if networkQAPowerSmoothed.IsZero() {
    78  		return rewardEstimate.Estimate()
    79  	}
    80  	expectedRewardForProvingPeriod := smoothing.ExtrapolatedCumSumOfRatio(projectionDuration, 0, rewardEstimate, networkQAPowerEstimate)
    81  	br128 := big.Mul(qaSectorPower, expectedRewardForProvingPeriod) // Q.0 * Q.128 => Q.128
    82  	br := big.Rsh(br128, math.Precision128)
    83  
    84  	return big.Max(br, big.Zero())
    85  }
    86  
    87  // BR but zero values are clamped at 1 attofil
    88  // Some uses of BR (PCD, IP) require a strictly positive value for BR derived values so
    89  // accounting variables can be used as succinct indicators of miner activity.
    90  func ExpectedRewardForPowerClampedAtAttoFIL(rewardEstimate, networkQAPowerEstimate smoothing.FilterEstimate, qaSectorPower abi.StoragePower, projectionDuration abi.ChainEpoch) abi.TokenAmount {
    91  	br := ExpectedRewardForPower(rewardEstimate, networkQAPowerEstimate, qaSectorPower, projectionDuration)
    92  	if br.LessThanEqual(big.Zero()) {
    93  		br = abi.NewTokenAmount(1)
    94  	}
    95  	return br
    96  }
    97  
    98  // The penalty for a sector continuing faulty for another proving period.
    99  // It is a projection of the expected reward earned by the sector.
   100  // Also known as "FF(t)"
   101  func PledgePenaltyForContinuedFault(rewardEstimate, networkQAPowerEstimate smoothing.FilterEstimate, qaSectorPower abi.StoragePower) abi.TokenAmount {
   102  	return ExpectedRewardForPower(rewardEstimate, networkQAPowerEstimate, qaSectorPower, ContinuedFaultProjectionPeriod)
   103  }
   104  
   105  // Lower bound on the penalty for a terminating sector.
   106  // It is a projection of the expected reward earned by the sector.
   107  // Also known as "SP(t)"
   108  func PledgePenaltyForTerminationLowerBound(rewardEstimate, networkQAPowerEstimate smoothing.FilterEstimate, qaSectorPower abi.StoragePower) abi.TokenAmount {
   109  	return ExpectedRewardForPower(rewardEstimate, networkQAPowerEstimate, qaSectorPower, TerminationPenaltyLowerBoundProjectionPeriod)
   110  }
   111  
   112  // Penalty to locked pledge collateral for the termination of a sector before scheduled expiry.
   113  // SectorAge is the time between the sector's activation and termination.
   114  // replacedDayReward and replacedSectorAge are the day reward and age of the replaced sector in a capacity upgrade.
   115  // They must be zero if no upgrade occurred.
   116  func PledgePenaltyForTermination(dayReward abi.TokenAmount, sectorAge abi.ChainEpoch,
   117  	twentyDayRewardAtActivation abi.TokenAmount, networkQAPowerEstimate smoothing.FilterEstimate,
   118  	qaSectorPower abi.StoragePower, rewardEstimate smoothing.FilterEstimate, replacedDayReward abi.TokenAmount,
   119  	replacedSectorAge abi.ChainEpoch) abi.TokenAmount {
   120  	// max(SP(t), BR(StartEpoch, 20d) + BR(StartEpoch, 1d) * terminationRewardFactor * min(SectorAgeInDays, 140))
   121  	// and sectorAgeInDays = sectorAge / EpochsInDay
   122  	lifetimeCap := abi.ChainEpoch(TerminationLifetimeCap) * builtin.EpochsInDay
   123  	cappedSectorAge := minEpoch(sectorAge, lifetimeCap)
   124  	// expected reward for lifetime of new sector (epochs*AttoFIL/day)
   125  	expectedReward := big.Mul(dayReward, big.NewInt(int64(cappedSectorAge)))
   126  	// if lifetime under cap and this sector replaced capacity, add expected reward for old sector's lifetime up to cap
   127  	relevantReplacedAge := minEpoch(replacedSectorAge, lifetimeCap-cappedSectorAge)
   128  	expectedReward = big.Add(expectedReward, big.Mul(replacedDayReward, big.NewInt(int64(relevantReplacedAge))))
   129  
   130  	penalizedReward := big.Mul(expectedReward, TerminationRewardFactor.Numerator)
   131  
   132  	return big.Max(
   133  		PledgePenaltyForTerminationLowerBound(rewardEstimate, networkQAPowerEstimate, qaSectorPower),
   134  		big.Add(
   135  			twentyDayRewardAtActivation,
   136  			big.Div(
   137  				penalizedReward,
   138  				big.Mul(big.NewInt(builtin.EpochsInDay), TerminationRewardFactor.Denominator)))) // (epochs*AttoFIL/day -> AttoFIL)
   139  }
   140  
   141  // The penalty for optimistically proving a sector with an invalid window PoSt.
   142  func PledgePenaltyForInvalidWindowPoSt(rewardEstimate, networkQAPowerEstimate smoothing.FilterEstimate, qaSectorPower abi.StoragePower) abi.TokenAmount {
   143  	return big.Add(
   144  		ExpectedRewardForPower(rewardEstimate, networkQAPowerEstimate, qaSectorPower, InvalidWindowPoStProjectionPeriod),
   145  		BasePenaltyForDisputedWindowPoSt,
   146  	)
   147  }
   148  
   149  // Computes the PreCommit deposit given sector qa weight and current network conditions.
   150  // PreCommit Deposit = BR(PreCommitDepositProjectionPeriod)
   151  func PreCommitDepositForPower(rewardEstimate, networkQAPowerEstimate smoothing.FilterEstimate, qaSectorPower abi.StoragePower) abi.TokenAmount {
   152  	return ExpectedRewardForPowerClampedAtAttoFIL(rewardEstimate, networkQAPowerEstimate, qaSectorPower, PreCommitDepositProjectionPeriod)
   153  }
   154  
   155  // Computes the pledge requirement for committing new quality-adjusted power to the network, given the current
   156  // network total and baseline power, per-epoch  reward, and circulating token supply.
   157  // The pledge comprises two parts:
   158  // - storage pledge, aka IP base: a multiple of the reward expected to be earned by newly-committed power
   159  // - consensus pledge, aka additional IP: a pro-rata fraction of the circulating money supply
   160  //
   161  // IP = IPBase(t) + AdditionalIP(t)
   162  // IPBase(t) = BR(t, InitialPledgeProjectionPeriod)
   163  // AdditionalIP(t) = LockTarget(t)*PledgeShare(t)
   164  // LockTarget = (LockTargetFactorNum / LockTargetFactorDenom) * FILCirculatingSupply(t)
   165  // PledgeShare(t) = sectorQAPower / max(BaselinePower(t), NetworkQAPower(t))
   166  func InitialPledgeForPower(qaPower, baselinePower abi.StoragePower, rewardEstimate, networkQAPowerEstimate smoothing.FilterEstimate, circulatingSupply abi.TokenAmount) abi.TokenAmount {
   167  	ipBase := ExpectedRewardForPowerClampedAtAttoFIL(rewardEstimate, networkQAPowerEstimate, qaPower, InitialPledgeProjectionPeriod)
   168  
   169  	lockTargetNum := big.Mul(InitialPledgeLockTarget.Numerator, circulatingSupply)
   170  	lockTargetDenom := InitialPledgeLockTarget.Denominator
   171  	pledgeShareNum := qaPower
   172  	networkQAPower := networkQAPowerEstimate.Estimate()
   173  	pledgeShareDenom := big.Max(big.Max(networkQAPower, baselinePower), qaPower) // use qaPower in case others are 0
   174  	additionalIPNum := big.Mul(lockTargetNum, pledgeShareNum)
   175  	additionalIPDenom := big.Mul(lockTargetDenom, pledgeShareDenom)
   176  	additionalIP := big.Div(additionalIPNum, additionalIPDenom)
   177  
   178  	nominalPledge := big.Add(ipBase, additionalIP)
   179  	spaceRacePledgeCap := big.Mul(InitialPledgeMaxPerByte, qaPower)
   180  	return big.Min(nominalPledge, spaceRacePledgeCap)
   181  }
   182  
   183  // Repays all fee debt and then verifies that the miner has amount needed to cover
   184  // the pledge requirement after burning all fee debt.  If not aborts.
   185  // Returns an amount that must be burnt by the actor.
   186  // Note that this call does not compute recent vesting so reported unlocked balance
   187  // may be slightly lower than the true amount. Computing vesting here would be
   188  // almost always redundant since vesting is quantized to ~daily units.  Vesting
   189  // will be at most one proving period old if computed in the cron callback.
   190  func RepayDebtsOrAbort(rt Runtime, st *State) abi.TokenAmount {
   191  	currBalance := rt.CurrentBalance()
   192  	toBurn, err := st.repayDebts(currBalance)
   193  	builtin.RequireNoErr(rt, err, exitcode.ErrIllegalState, "unlocked balance can not repay fee debt")
   194  
   195  	return toBurn
   196  }
   197  
   198  func ConsensusFaultPenalty(thisEpochReward abi.TokenAmount) abi.TokenAmount {
   199  	return big.Div(
   200  		big.Mul(thisEpochReward, big.NewInt(ConsensusFaultFactor)),
   201  		big.NewInt(builtin.ExpectedLeadersPerEpoch),
   202  	)
   203  }
   204  
   205  // Returns the amount of a reward to vest, and the vesting schedule, for a reward amount.
   206  func LockedRewardFromReward(reward abi.TokenAmount) (abi.TokenAmount, *VestSpec) {
   207  	// Locked amount is 75% of award.
   208  	lockAmount := big.Div(big.Mul(reward, LockedRewardFactorNum), LockedRewardFactorDenom)
   209  	return lockAmount, &RewardVestingSpec
   210  }