-
Notifications
You must be signed in to change notification settings - Fork 0
/
reward.go
162 lines (144 loc) · 7.93 KB
/
reward.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package nv4
import (
"context"
"golang.org/x/xerrors"
"github.com/chenjianmei111/go-state-types/abi"
"github.com/chenjianmei111/go-state-types/big"
reward0 "github.com/chenjianmei111/specs-actors/actors/builtin/reward"
cid "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
builtin2 "github.com/chenjianmei111/specs-actors/v2/actors/builtin"
power2 "github.com/chenjianmei111/specs-actors/v2/actors/builtin/power"
reward2 "github.com/chenjianmei111/specs-actors/v2/actors/builtin/reward"
"github.com/chenjianmei111/specs-actors/v2/actors/states"
math2 "github.com/chenjianmei111/specs-actors/v2/actors/util/math"
smoothing2 "github.com/chenjianmei111/specs-actors/v2/actors/util/smoothing"
)
var (
// Q.128 coefficients used to compute new effective network time
// (g*Tau is the BaselineExponent, B0 is the BaselineInitialValue)
gTauOverB0 big.Int
oneOverGTau big.Int
)
func init() {
constStrs := []string{
"77669179383316",
"516058975841646949912583456815941211282956743",
}
constBigs := math2.Parse(constStrs)
gTauOverB0 = big.NewFromGo(constBigs[0]) // Q.128
oneOverGTau = big.NewFromGo(constBigs[1])
}
type rewardMigrator struct {
actorsOut *states.Tree
}
func (m rewardMigrator) MigrateState(ctx context.Context, store cbor.IpldStore, head cid.Cid, migInfo MigrationInfo) (*StateMigrationResult, error) {
var inState reward0.State
if err := store.Get(ctx, head, &inState); err != nil {
return nil, err
}
// Get migrated power actor's ThisEpochRawBytePower
outPowerAct, found, err := m.actorsOut.GetActor(builtin2.StoragePowerActorAddr)
if err != nil {
return nil, err
}
if !found {
return nil, xerrors.Errorf("could not find power actor in migrated state")
}
var outPowerSt power2.State
if err := store.Get(ctx, outPowerAct.Head, &outPowerSt); err != nil {
return nil, xerrors.Errorf("failed to read migrated power actor state %w", err)
}
thisEpochRawBytePower := outPowerSt.ThisEpochRawBytePower
one := big.Lsh(big.NewInt(1), math2.Precision128) // Q.128
// Set baseline to the value it would be at the end of the prior epoch if
// current parameters had been in place at network start
outThisEpochBaselinePower := math2.ExpBySquaring(reward2.BaselineExponent, int64(migInfo.priorEpoch)) // Q.128
outThisEpochBaselinePower = big.Mul(reward2.BaselineInitialValue, outThisEpochBaselinePower) // Q.0 * Q.128 => Q.128
outThisEpochBaselinePower = big.Rsh(outThisEpochBaselinePower, math2.Precision128) // Q.128 => Q.0
// Set effective network power to the value it would be at the end of the
// prior epoch if the current parameters had been in place at network start
cumSumRealized := big.Lsh(inState.CumsumRealized, math2.Precision128) // Q.0 => Q.128
acc0 := big.Mul(cumSumRealized, gTauOverB0) // Q.128 * Q.128 => Q.256
acc0 = big.Rsh(acc0, math2.Precision128) // Q.256 => Q.128
acc0 = big.Add(acc0, one)
acc0 = math2.Ln(acc0)
acc0 = big.Mul(acc0, oneOverGTau) // Q.128 * Q.128 => Q.256
postUpgradeTheta := big.Rsh(acc0, math2.Precision128) // Q.256 => Q.128
effNetworkTime := big.Rsh(postUpgradeTheta, math2.Precision128) // Q.128 => Q.0
effNetworkTime = big.Add(effNetworkTime, big.NewInt(1))
if !effNetworkTime.Int.IsInt64() {
return nil, xerrors.Errorf("new effective network time chain epoch out of bounds %v", effNetworkTime)
}
outEffectiveNetworkTime := abi.ChainEpoch(effNetworkTime.Int.Int64())
// Set effective baseline power given the new effective network time and
// baseline function.
outEffectiveBaselinePower := math2.ExpBySquaring(reward2.BaselineExponent, int64(outEffectiveNetworkTime)) // Q.128
outEffectiveBaselinePower128 := big.Mul(reward2.BaselineInitialValue, outEffectiveBaselinePower) // Q.0 * Q.128 => Q.128
outEffectiveBaselinePower = big.Rsh(outEffectiveBaselinePower128, math2.Precision128) // Q.128 => Q.0
// Set cumsum baseline given new effective network time and baseline function
outCumSumBaseline := big.Sub(outEffectiveBaselinePower128, big.Lsh(reward2.BaselineInitialValue, math2.Precision128)) // Q.128 - Q.128 => Q.128
outCumSumBaseline = big.Mul(outCumSumBaseline, oneOverGTau) // Q.128 * Q.128 => Q.256
outCumSumBaseline = big.Rsh(outCumSumBaseline, 2*math2.Precision128) // Q.256 => Q.0
// Reduce baseline total so that the amount of tokens remaining to be minted is held fixed across the upgrade
preUpgradeTheta := reward2.ComputeRTheta(inState.EffectiveNetworkTime, inState.EffectiveBaselinePower, inState.CumsumRealized, inState.CumsumBaseline) // Q.128
thetaDiff := big.Sub(preUpgradeTheta, postUpgradeTheta)
baselineAdjustmentExp := big.Mul(reward2.Lambda, thetaDiff) // Q.128 * Q.128 => Q.256
baselineAdjustmentExp = big.Rsh(baselineAdjustmentExp, math2.Precision128) // Q.256 => Q.128
baselineAdjustment := big.NewFromGo(math2.ExpNeg(baselineAdjustmentExp.Int))
outBaselineTotal := big.Mul(reward0.BaselineTotal, baselineAdjustment) // Q.0 * Q.128 => Q.128
outBaselineTotal = big.Rsh(outBaselineTotal, math2.Precision128) // Q.128 => Q.0
// Set reward filter postiion and velocity values
// Filter position is set by evaluating the closed form expression for expected
// block reward at a particular epoch assuming that the new baseline function
// had been in place at network start
acc1 := big.Mul(reward2.BaselineInitialValue, oneOverGTau) // Q.0 * Q.128 => Q.128
acc1 = big.Add(acc1, big.Lsh(inState.CumsumRealized, math2.Precision128))
rawBytePower256 := big.Lsh(thisEpochRawBytePower, 2*math2.Precision128) // Q.0 => Q.256
acc1 = big.Div(rawBytePower256, acc1) // Q.256 / Q.128 => Q.128
acc1 = big.Add(acc1, one)
acc1 = math2.Ln(acc1)
acc1 = big.Lsh(acc1, math2.Precision128) // Q.128 => Q.256
acc1 = big.Div(acc1, big.Lsh(big.NewInt(6), math2.Precision128)) // Q.256 / Q.128 => Q.128
acc1 = big.NewFromGo(math2.ExpNeg(acc1.Int))
acc1 = big.Sub(one, acc1)
acc2 := big.Mul(postUpgradeTheta, reward2.Lambda) // Q.128 * Q.128 => Q.256
acc2 = big.Rsh(acc2, math2.Precision128) // Q.256 => Q.128
acc2 = big.NewFromGo(math2.ExpNeg(acc2.Int))
acc1 = big.Mul(acc1, acc2) //Q.128 * Q.128 => Q.256
acc1 = big.Rsh(acc1, math2.Precision128) // Q.256 => Q.128
acc1 = big.Mul(acc1, outBaselineTotal) // Q.128 * Q.0 => Q.128
acc3 := big.Mul(big.NewInt(int64(migInfo.priorEpoch)), reward2.Lambda) // Q.0 * Q.128 => Q.128
acc3 = big.NewFromGo(math2.ExpNeg(acc3.Int))
acc3 = big.Mul(acc3, reward0.SimpleTotal) // Q.128 * Q.0 => Q.128
acc3 = big.Mul(acc3, reward2.ExpLamSubOne) // Q.128 * Q.128 => Q.256
acc3 = big.Rsh(acc3, math2.Precision128) // Q.256 => Q.128
outRewardSmoothedPosition := big.Add(acc1, acc3)
// Filter velocity precision is less important. Hard coded value of 31 x 10^51 is sufficient
outRewardSmoothedVelocity := big.Mul(
big.NewInt(31),
big.Exp(big.NewInt(10), big.NewInt(51)),
) // Q.128
outThisEpochRewardSmoothed := smoothing2.FilterEstimate{
PositionEstimate: outRewardSmoothedPosition,
VelocityEstimate: outRewardSmoothedVelocity,
}
outState := reward2.State{
CumsumBaseline: outCumSumBaseline,
CumsumRealized: inState.CumsumRealized,
EffectiveNetworkTime: outEffectiveNetworkTime,
EffectiveBaselinePower: outEffectiveBaselinePower,
ThisEpochReward: inState.ThisEpochReward,
ThisEpochRewardSmoothed: outThisEpochRewardSmoothed,
ThisEpochBaselinePower: outThisEpochBaselinePower,
Epoch: inState.Epoch,
TotalStoragePowerReward: inState.TotalMined,
SimpleTotal: reward0.SimpleTotal,
BaselineTotal: outBaselineTotal,
}
newHead, err := store.Put(ctx, &outState)
return &StateMigrationResult{
NewHead: newHead,
Transfer: big.Zero(),
}, err
}