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 }