github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/builtin/miner/miner_internal_test.go (about) 1 package miner 2 3 import ( 4 "testing" 5 6 "github.com/filecoin-project/go-state-types/abi" 7 "github.com/filecoin-project/go-state-types/big" 8 "github.com/minio/blake2b-simd" 9 "github.com/stretchr/testify/assert" 10 11 "github.com/filecoin-project/specs-actors/v4/actors/builtin" 12 "github.com/filecoin-project/specs-actors/v4/actors/util/smoothing" 13 tutils "github.com/filecoin-project/specs-actors/v4/support/testing" 14 ) 15 16 func TestAssignProvingPeriodBoundary(t *testing.T) { 17 addr1 := tutils.NewActorAddr(t, "a") 18 addr2 := tutils.NewActorAddr(t, "b") 19 startEpoch := abi.ChainEpoch(1) 20 21 // ensure the values are different for different addresses 22 b1, err := assignProvingPeriodOffset(addr1, startEpoch, blake2b.Sum256) 23 assert.NoError(t, err) 24 assert.True(t, b1 >= 0) 25 assert.True(t, b1 < WPoStProvingPeriod) 26 27 b2, err := assignProvingPeriodOffset(addr2, startEpoch, blake2b.Sum256) 28 assert.NoError(t, err) 29 assert.True(t, b2 >= 0) 30 assert.True(t, b2 < WPoStProvingPeriod) 31 32 assert.NotEqual(t, b1, b2) 33 34 // Ensure boundaries are always less than a proving period. 35 for i := 0; i < 10_000; i++ { 36 boundary, err := assignProvingPeriodOffset(addr1, abi.ChainEpoch(i), blake2b.Sum256) 37 assert.NoError(t, err) 38 assert.True(t, boundary >= 0) 39 assert.True(t, boundary < WPoStProvingPeriod) 40 } 41 } 42 43 func TestCurrentProvingPeriodStart(t *testing.T) { 44 // At epoch zero... 45 curr := e(0) 46 47 // ... with offset zero, the current proving period starts now, ... 48 assert.Equal(t, e(0), currentProvingPeriodStart(curr, 0)) 49 50 // ... and all other offsets are negative. 51 assert.Equal(t, -WPoStProvingPeriod+1, currentProvingPeriodStart(curr, 1)) 52 assert.Equal(t, -WPoStProvingPeriod+10, currentProvingPeriodStart(curr, 10)) 53 assert.Equal(t, e(-1), currentProvingPeriodStart(curr, WPoStProvingPeriod-1)) 54 55 // At epoch 1, offsets 0 and 1 start at offset, but offsets 2 and later start in the past. 56 curr = 1 57 assert.Equal(t, e(0), currentProvingPeriodStart(curr, 0)) 58 assert.Equal(t, e(1), currentProvingPeriodStart(curr, 1)) 59 assert.Equal(t, -WPoStProvingPeriod+2, currentProvingPeriodStart(curr, 2)) 60 assert.Equal(t, -WPoStProvingPeriod+3, currentProvingPeriodStart(curr, 3)) 61 assert.Equal(t, e(-1), currentProvingPeriodStart(curr, WPoStProvingPeriod-1)) 62 63 // An arbitrary mid-period epoch. 64 curr = 123 65 assert.Equal(t, e(0), currentProvingPeriodStart(curr, 0)) 66 assert.Equal(t, e(1), currentProvingPeriodStart(curr, 1)) 67 assert.Equal(t, e(122), currentProvingPeriodStart(curr, 122)) 68 assert.Equal(t, e(123), currentProvingPeriodStart(curr, 123)) 69 assert.Equal(t, -WPoStProvingPeriod+124, currentProvingPeriodStart(curr, 124)) 70 assert.Equal(t, e(-1), currentProvingPeriodStart(curr, WPoStProvingPeriod-1)) 71 72 // The final epoch in the chain's first full period 73 curr = WPoStProvingPeriod - 1 74 assert.Equal(t, e(0), currentProvingPeriodStart(curr, 0)) 75 assert.Equal(t, e(1), currentProvingPeriodStart(curr, 1)) 76 assert.Equal(t, e(2), currentProvingPeriodStart(curr, 2)) 77 assert.Equal(t, WPoStProvingPeriod-2, currentProvingPeriodStart(curr, WPoStProvingPeriod-2)) 78 assert.Equal(t, WPoStProvingPeriod-1, currentProvingPeriodStart(curr, WPoStProvingPeriod-1)) 79 80 // Into the chain's second period 81 curr = WPoStProvingPeriod 82 assert.Equal(t, WPoStProvingPeriod, currentProvingPeriodStart(curr, 0)) 83 assert.Equal(t, e(1), currentProvingPeriodStart(curr, 1)) 84 assert.Equal(t, e(2), currentProvingPeriodStart(curr, 2)) 85 assert.Equal(t, WPoStProvingPeriod-1, currentProvingPeriodStart(curr, WPoStProvingPeriod-1)) 86 87 curr = WPoStProvingPeriod + 234 88 assert.Equal(t, WPoStProvingPeriod, currentProvingPeriodStart(curr, 0)) 89 assert.Equal(t, WPoStProvingPeriod+1, currentProvingPeriodStart(curr, 1)) 90 assert.Equal(t, WPoStProvingPeriod+233, currentProvingPeriodStart(curr, 233)) 91 assert.Equal(t, WPoStProvingPeriod+234, currentProvingPeriodStart(curr, 234)) 92 assert.Equal(t, e(235), currentProvingPeriodStart(curr, 235)) 93 assert.Equal(t, WPoStProvingPeriod-1, currentProvingPeriodStart(curr, WPoStProvingPeriod-1)) 94 } 95 96 type e = abi.ChainEpoch 97 98 func TestFaultFeeInvariants(t *testing.T) { 99 100 // Construct plausible reward and qa power filtered estimates 101 epochReward := abi.NewTokenAmount(100 << 53) 102 rewardEstimate := smoothing.TestingConstantEstimate(epochReward) // not too much growth over ~3000 epoch projection in BR 103 104 networkPower := abi.NewStoragePower(100 << 50) 105 powerEstimate := smoothing.TestingConstantEstimate(networkPower) 106 107 // constant filter estimate cumsum ratio is just multiplication and division 108 // test that internal precision of BR calculation does not cost accuracy 109 // compared to simple multiplication in this case. 110 t.Run("br looks right in plausible (sectorPower, networkPower, reward) range", func(t *testing.T) { 111 // between 10 and 100 FIL is reasonable for near-mid future 112 tensOfFIL := big.Mul(abi.NewTokenAmount(1e18), big.NewInt(50)) 113 rewardEstimate := smoothing.TestingConstantEstimate(tensOfFIL) 114 smallPower := big.NewInt(32 << 30) // 32 GiB 115 hugePower := big.NewInt(1 << 60) // 1 EiB 116 epochsPerDay := big.NewInt(builtin.EpochsInDay) 117 smallPowerBRNum := big.Mul(big.Mul(smallPower, epochsPerDay), tensOfFIL) 118 hugePowerBRNum := big.Mul(big.Mul(hugePower, epochsPerDay), tensOfFIL) 119 120 // QAPower = Space * AverageQuality 121 // 10s of EiBs -- lower range 122 // 1.2e18 * 10 bytes * 1 quality ~ 1e19 123 tensOfEiBs := big.Mul(abi.NewStoragePower(1e18), big.NewInt(10)) 124 lowPowerEstimate := smoothing.TestingConstantEstimate(tensOfEiBs) 125 brSmallLow := ExpectedRewardForPower(rewardEstimate, lowPowerEstimate, smallPower, builtin.EpochsInDay) 126 brHugeLow := ExpectedRewardForPower(rewardEstimate, lowPowerEstimate, hugePower, builtin.EpochsInDay) 127 assert.Equal(t, big.Div(smallPowerBRNum, tensOfEiBs), brSmallLow) 128 assert.Equal(t, big.Div(hugePowerBRNum, tensOfEiBs), brHugeLow) 129 130 // 100s of EiBs 131 // 1.2e18 * 100 bytes * 5 quality ~ 6e20 132 hundredsOfEiBs := big.Mul(abi.NewStoragePower(1e18), big.NewInt(6e2)) 133 midPowerEstimate := smoothing.TestingConstantEstimate(hundredsOfEiBs) 134 brSmallMid := ExpectedRewardForPower(rewardEstimate, midPowerEstimate, smallPower, builtin.EpochsInDay) 135 brHugeMid := ExpectedRewardForPower(rewardEstimate, midPowerEstimate, hugePower, builtin.EpochsInDay) 136 assert.Equal(t, big.Div(smallPowerBRNum, hundredsOfEiBs), brSmallMid) 137 assert.Equal(t, big.Div(hugePowerBRNum, hundredsOfEiBs), brHugeMid) 138 139 // 1000s of EiBs -- upper range 140 // 1.2e18 * 1000 bytes * 10 quality = 1.2e22 ~ 2e22 141 thousandsOfEiBs := big.Mul(abi.NewStoragePower(1e18), big.NewInt(2e4)) 142 upperPowerEstimate := smoothing.TestingConstantEstimate(thousandsOfEiBs) 143 brSmallUpper := ExpectedRewardForPower(rewardEstimate, upperPowerEstimate, smallPower, builtin.EpochsInDay) 144 brHugeUpper := ExpectedRewardForPower(rewardEstimate, upperPowerEstimate, hugePower, builtin.EpochsInDay) 145 assert.Equal(t, big.Div(smallPowerBRNum, thousandsOfEiBs), brSmallUpper) 146 assert.Equal(t, big.Div(hugePowerBRNum, thousandsOfEiBs), brHugeUpper) 147 }) 148 149 t.Run("Declared and Undeclared fault penalties are linear over sectorQAPower term", func(t *testing.T) { 150 151 faultySectorAPower := abi.NewStoragePower(1 << 50) 152 faultySectorBPower := abi.NewStoragePower(19 << 50) 153 faultySectorCPower := abi.NewStoragePower(63 << 50) 154 totalFaultPower := big.Add(big.Add(faultySectorAPower, faultySectorBPower), faultySectorCPower) 155 156 // Declared faults 157 ffA := PledgePenaltyForContinuedFault(rewardEstimate, powerEstimate, faultySectorAPower) 158 ffB := PledgePenaltyForContinuedFault(rewardEstimate, powerEstimate, faultySectorBPower) 159 ffC := PledgePenaltyForContinuedFault(rewardEstimate, powerEstimate, faultySectorCPower) 160 161 ffAll := PledgePenaltyForContinuedFault(rewardEstimate, powerEstimate, totalFaultPower) 162 163 // Because we can introduce rounding error between 1 and zero for every penalty calculation 164 // we can at best expect n calculations of 1 power to be within n of 1 calculation of n powers. 165 diff := big.Sub(ffAll, big.Add(ffC, big.Add(ffA, ffB))) 166 assert.True(t, diff.GreaterThanEqual(big.Zero())) 167 assert.True(t, diff.LessThan(big.NewInt(3))) 168 169 // Undeclared faults 170 spA := PledgePenaltyForTerminationLowerBound(rewardEstimate, powerEstimate, faultySectorAPower) 171 spB := PledgePenaltyForTerminationLowerBound(rewardEstimate, powerEstimate, faultySectorBPower) 172 spC := PledgePenaltyForTerminationLowerBound(rewardEstimate, powerEstimate, faultySectorCPower) 173 174 spAll := PledgePenaltyForTerminationLowerBound(rewardEstimate, powerEstimate, totalFaultPower) 175 176 // Because we can introduce rounding error between 1 and zero for every penalty calculation 177 // we can at best expect n calculations of 1 power to be within n of 1 calculation of n powers. 178 diff = big.Sub(spAll, big.Add(spC, big.Add(spA, spB))) 179 assert.True(t, diff.GreaterThanEqual(big.Zero())) 180 assert.True(t, diff.LessThan(big.NewInt(3))) 181 182 }) 183 }