github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/builtin/reward/reward_logic_test.go (about) 1 package reward 2 3 import ( 4 "bytes" 5 "fmt" 6 gbig "math/big" 7 "testing" 8 9 "github.com/filecoin-project/go-state-types/abi" 10 "github.com/filecoin-project/go-state-types/big" 11 "github.com/stretchr/testify/assert" 12 "github.com/xorcare/golden" 13 14 "github.com/filecoin-project/specs-actors/v4/actors/builtin" 15 "github.com/filecoin-project/specs-actors/v4/actors/util/math" 16 ) 17 18 func q128ToF(x big.Int) float64 { 19 q128 := new(gbig.Int).SetInt64(1) 20 q128 = q128.Lsh(q128, math.Precision128) 21 res, _ := new(gbig.Rat).SetFrac(x.Int, q128).Float64() 22 return res 23 } 24 25 func TestComputeRTeta(t *testing.T) { 26 baselinePowerAt := func(epoch abi.ChainEpoch) abi.StoragePower { 27 return big.Mul(big.NewInt(int64(epoch+1)), big.NewInt(2048)) 28 } 29 30 assert.Equal(t, 0.5, q128ToF(ComputeRTheta(1, baselinePowerAt(1), big.NewInt(2048+2*2048*0.5), big.NewInt(2048+2*2048)))) 31 assert.Equal(t, 0.25, q128ToF(ComputeRTheta(1, baselinePowerAt(1), big.NewInt(2048+2*2048*0.25), big.NewInt(2048+2*2048)))) 32 33 cumsum15 := big.NewInt(0) 34 for i := abi.ChainEpoch(0); i < 16; i++ { 35 cumsum15 = big.Add(cumsum15, baselinePowerAt(i)) 36 } 37 assert.Equal(t, 15.25, q128ToF(ComputeRTheta(16, 38 baselinePowerAt(16), 39 big.Add(cumsum15, big.Div(baselinePowerAt(16), big.NewInt(4))), 40 big.Add(cumsum15, baselinePowerAt(16))))) 41 } 42 43 func TestBaselineReward(t *testing.T) { 44 step := gbig.NewInt(5000) 45 step = step.Lsh(step, math.Precision128) 46 step = step.Sub(step, gbig.NewInt(77777777777)) // offset from full integers 47 48 delta := gbig.NewInt(1) 49 delta = delta.Lsh(delta, math.Precision128) 50 delta = delta.Sub(delta, gbig.NewInt(33333333333)) // offset from full integers 51 52 prevTheta := new(gbig.Int) 53 theta := new(gbig.Int).Set(delta) 54 55 b := &bytes.Buffer{} 56 b.WriteString("t0, t1, y\n") 57 simple := computeReward(0, big.Zero(), big.Zero(), DefaultSimpleTotal, DefaultBaselineTotal) 58 59 for i := 0; i < 512; i++ { 60 reward := computeReward(0, big.NewFromGo(prevTheta), big.NewFromGo(theta), DefaultSimpleTotal, DefaultBaselineTotal) 61 reward = big.Sub(reward, simple) 62 fmt.Fprintf(b, "%s,%s,%s\n", prevTheta, theta, reward.Int) 63 prevTheta = prevTheta.Add(prevTheta, step) 64 theta = theta.Add(theta, step) 65 } 66 67 golden.Assert(t, b.Bytes()) 68 } 69 70 func TestSimpleReward(t *testing.T) { 71 b := &bytes.Buffer{} 72 b.WriteString("x, y\n") 73 for i := int64(0); i < 512; i++ { 74 x := i * 5000 75 reward := computeReward(abi.ChainEpoch(x), big.Zero(), big.Zero(), DefaultSimpleTotal, DefaultBaselineTotal) 76 fmt.Fprintf(b, "%d,%s\n", x, reward.Int) 77 } 78 79 golden.Assert(t, b.Bytes()) 80 } 81 82 func TestBaselineRewardGrowth(t *testing.T) { 83 84 baselineInYears := func(start abi.StoragePower, x abi.ChainEpoch) abi.StoragePower { 85 baseline := start 86 for i := abi.ChainEpoch(0); i < x*builtin.EpochsInYear; i++ { 87 baseline = BaselinePowerFromPrev(baseline) 88 } 89 return baseline 90 } 91 92 // Baseline reward should have 100% growth rate 93 // This implies that for every year x, the baseline function should be: 94 // StartVal * 2^x. 95 // 96 // Error values for 1 years of growth were determined empirically with latest 97 // baseline power construction to set bounds in this test in order to 98 // 1. throw a test error if function changes and percent error goes up 99 // 2. serve as documentation of current error bounds 100 type growthTestCase struct { 101 StartVal abi.StoragePower 102 ErrBound float64 103 } 104 cases := []growthTestCase{ 105 // 1 byte 106 { 107 abi.NewStoragePower(1), 108 1, 109 }, 110 // GiB 111 { 112 abi.NewStoragePower(1 << 30), 113 1e-3, 114 }, 115 // TiB 116 { 117 abi.NewStoragePower(1 << 40), 118 1e-6, 119 }, 120 // PiB 121 { 122 abi.NewStoragePower(1 << 50), 123 1e-8, 124 }, 125 // EiB 126 { 127 BaselineInitialValue, 128 1e-8, 129 }, 130 // ZiB 131 { 132 big.Lsh(big.NewInt(1), 70), 133 1e-8, 134 }, 135 // non power of 2 ~ 1 EiB 136 { 137 abi.NewStoragePower(513633559722596517), 138 1e-8, 139 }, 140 } 141 for _, testCase := range cases { 142 years := int64(1) 143 end := baselineInYears(testCase.StartVal, abi.ChainEpoch(1)) 144 145 multiplier := big.Exp(big.NewInt(2), big.NewInt(years)) // keeping this generalized in case we want to test more years 146 expected := big.Mul(testCase.StartVal, multiplier) 147 diff := big.Sub(expected, end) 148 149 perrFrac := gbig.NewRat(1, 1).SetFrac(diff.Int, expected.Int) 150 perr, _ := perrFrac.Float64() 151 152 assert.Less(t, perr, testCase.ErrBound) 153 } 154 }