github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/builtin/miner/policy_test.go (about) 1 package miner_test 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/stretchr/testify/assert" 9 10 "github.com/filecoin-project/specs-actors/v4/actors/builtin" 11 "github.com/filecoin-project/specs-actors/v4/actors/builtin/miner" 12 ) 13 14 func TestQuality(t *testing.T) { 15 // Quality of space with no deals. This doesn't depend on either the sector size or duration. 16 emptyQuality := big.NewIntUnsigned(1 << builtin.SectorQualityPrecision) 17 // Quality space filled with non-verified deals. 18 dealQuality := big.Mul(emptyQuality, big.Div(builtin.DealWeightMultiplier, builtin.QualityBaseMultiplier)) 19 // Quality space filled with verified deals. 20 verifiedQuality := big.Mul(emptyQuality, big.Div(builtin.VerifiedDealWeightMultiplier, builtin.QualityBaseMultiplier)) 21 22 t.Run("quality is independent of size and duration", func(t *testing.T) { 23 for _, size := range []abi.SectorSize{1, 10, 1 << 10, 32 << 30, 1 << 40} { 24 for _, duration := range []abi.ChainEpoch{1, 10, 1000, 1000 * builtin.EpochsInDay} { 25 sectorWeight := weight(size, duration) 26 assertEqual(t, emptyQuality, miner.QualityForWeight(size, duration, big.Zero(), big.Zero())) 27 assertEqual(t, dealQuality, miner.QualityForWeight(size, duration, sectorWeight, big.Zero())) 28 assertEqual(t, verifiedQuality, miner.QualityForWeight(size, duration, big.Zero(), sectorWeight)) 29 } 30 } 31 }) 32 33 t.Run("quality scales with verified weight proportion", func(t *testing.T) { 34 sectorSize := abi.SectorSize(1 << 40) 35 sectorDuration := abi.ChainEpoch(1_000_000) // ~350 days 36 sectorWeight := weight(sectorSize, sectorDuration) 37 38 for _, verifiedSpace := range []abi.SectorSize{0, 1, 1 << 10, 2 << 20, 5 << 20, 1 << 30, sectorSize - 1, sectorSize} { 39 emptyWeight := weight(sectorSize-verifiedSpace, sectorDuration) 40 verifiedWeight := weight(verifiedSpace, sectorDuration) 41 assertEqual(t, big.Sub(sectorWeight, emptyWeight), verifiedWeight) 42 43 // Expect sector quality to be a weighted sum of base and verified quality. 44 eq := big.Mul(emptyWeight, emptyQuality) 45 vq := big.Mul(verifiedWeight, verifiedQuality) 46 expectedQuality := big.Div(big.Sum(eq, vq), sectorWeight) 47 assertEqual(t, expectedQuality, miner.QualityForWeight(sectorSize, sectorDuration, big.Zero(), verifiedWeight)) 48 } 49 }) 50 } 51 52 func TestPower(t *testing.T) { 53 t.Run("empty sector has power equal to size", func(t *testing.T) { 54 for _, size := range []abi.SectorSize{1, 10, 1 << 10, 32 << 30, 1 << 40} { 55 for _, duration := range []abi.ChainEpoch{1, 10, 1000, 1000 * builtin.EpochsInDay} { 56 expectedPower := big.NewInt(int64(size)) 57 assert.Equal(t, expectedPower, miner.QAPowerForWeight(size, duration, big.Zero(), big.Zero())) 58 } 59 } 60 }) 61 62 t.Run("verified sector has power a multiple of size", func(t *testing.T) { 63 // Assumes the multiplier is an integer. 64 verifiedMultiplier := big.Div(builtin.VerifiedDealWeightMultiplier, builtin.QualityBaseMultiplier).Int64() 65 for _, size := range []abi.SectorSize{1, 10, 1 << 10, 32 << 30, 1 << 40} { 66 for _, duration := range []abi.ChainEpoch{1, 10, 1000, 1000 * builtin.EpochsInDay} { 67 verifiedWeight := weight(size, duration) 68 expectedPower := big.NewInt(int64(size) * verifiedMultiplier) 69 assert.Equal(t, expectedPower, miner.QAPowerForWeight(size, duration, big.Zero(), verifiedWeight)) 70 } 71 } 72 }) 73 74 t.Run("verified weight adds proportional power", func(t *testing.T) { 75 sectorSize := abi.SectorSize(1 << 40) 76 sectorDuration := abi.ChainEpoch(180 * builtin.SecondsInDay) 77 sectorWeight := weight(sectorSize, sectorDuration) 78 79 fullyEmptyPower := big.NewInt(int64(sectorSize)) 80 fullyVerifiedPower := big.Div(big.Mul(big.NewInt(int64(sectorSize)), builtin.VerifiedDealWeightMultiplier), builtin.QualityBaseMultiplier) 81 82 maxError := big.NewInt(1 << builtin.SectorQualityPrecision) 83 84 for _, verifiedSpace := range []abi.SectorSize{0, 1, 1 << 10, 5 << 20, 32 << 30, sectorSize - 1, sectorSize} { 85 for _, verifiedDuration := range []abi.ChainEpoch{0, 1, sectorDuration / 2, sectorDuration - 1, sectorDuration} { 86 verifiedWeight := weight(verifiedSpace, verifiedDuration) 87 emptyWeight := big.Sub(sectorWeight, verifiedWeight) 88 89 // Expect sector power to be a weighted sum of base and verified power. 90 ep := big.Mul(emptyWeight, fullyEmptyPower) 91 vp := big.Mul(verifiedWeight, fullyVerifiedPower) 92 expectedPower := big.Div(big.Sum(ep, vp), sectorWeight) 93 power := miner.QAPowerForWeight(sectorSize, sectorDuration, big.Zero(), verifiedWeight) 94 powerError := big.Sub(expectedPower, power) 95 assert.True(t, powerError.LessThanEqual(maxError)) 96 } 97 } 98 }) 99 100 t.Run("demonstrate standard sectors", func(t *testing.T) { 101 sectorDuration := abi.ChainEpoch(180 * builtin.EpochsInDay) 102 vmul := big.Div(builtin.VerifiedDealWeightMultiplier, builtin.QualityBaseMultiplier).Int64() 103 104 { 105 // 32 GiB 106 sectorSize := abi.SectorSize(32 << 30) 107 sectorWeight := weight(sectorSize, sectorDuration) 108 109 assert.Equal(t, big.NewInt(1*32<<30), miner.QAPowerForWeight(sectorSize, sectorDuration, big.Zero(), big.Zero())) 110 assert.Equal(t, big.NewInt(vmul*32<<30), miner.QAPowerForWeight(sectorSize, sectorDuration, big.Zero(), sectorWeight)) 111 halfVerifiedPower := big.NewInt((1 * 32 << 30 / 2) + (vmul * 32 << 30 / 2)) 112 assert.Equal(t, halfVerifiedPower, miner.QAPowerForWeight(sectorSize, sectorDuration, big.Zero(), big.Div(sectorWeight, big.NewInt(2)))) 113 } 114 { 115 // 64 GiB 116 sectorSize := abi.SectorSize(64 << 30) 117 sectorWeight := weight(sectorSize, sectorDuration) 118 119 assert.Equal(t, big.NewInt(1*64<<30), miner.QAPowerForWeight(sectorSize, sectorDuration, big.Zero(), big.Zero())) 120 assert.Equal(t, big.NewInt(vmul*64<<30), miner.QAPowerForWeight(sectorSize, sectorDuration, big.Zero(), sectorWeight)) 121 halfVerifiedPower := big.NewInt((1 * 64 << 30 / 2) + (vmul * 64 << 30 / 2)) 122 assert.Equal(t, halfVerifiedPower, miner.QAPowerForWeight(sectorSize, sectorDuration, big.Zero(), big.Div(sectorWeight, big.NewInt(2)))) 123 } 124 { 125 // 1 TiB 126 sectorSize := abi.SectorSize(1 << 40) 127 sectorWeight := weight(sectorSize, sectorDuration) 128 129 assert.Equal(t, big.NewInt(1*1<<40), miner.QAPowerForWeight(sectorSize, sectorDuration, big.Zero(), big.Zero())) 130 assert.Equal(t, big.NewInt(vmul*1<<40), miner.QAPowerForWeight(sectorSize, sectorDuration, big.Zero(), sectorWeight)) 131 halfVerifiedPower := big.NewInt((1 * 1 << 40 / 2) + (vmul * 1 << 40 / 2)) 132 assert.Equal(t, halfVerifiedPower, miner.QAPowerForWeight(sectorSize, sectorDuration, big.Zero(), big.Div(sectorWeight, big.NewInt(2)))) 133 } 134 }) 135 } 136 137 func weight(size abi.SectorSize, duration abi.ChainEpoch) big.Int { 138 return big.Mul(big.NewIntUnsigned(uint64(size)), big.NewInt(int64(duration))) 139 } 140 141 func assertEqual(t *testing.T, a, b big.Int) { 142 // Zero does not have a canonical representation, so check that explicitly. 143 if !(a.IsZero() && b.IsZero()) { 144 assert.Equal(t, a, b) 145 } 146 }