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  }