github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/store/mainchain/account_level/level_math.go (about) 1 package account_level 2 3 import ( 4 "math/big" 5 "sync" 6 ) 7 8 var ( 9 minM = big.NewRat(570e8, 1) 10 ratU = big.NewRat(1e8, 1) 11 ratC = big.NewRat(1, 8640) 12 ratX = big.NewRat(1, 1) 13 ratN = big.NewRat(-1, 1) 14 dratMax = big.NewRat(16, 100) 15 dratL2 = big.NewRat(1, 10) 16 dratL1 = big.NewRat(8, 100) 17 dratS = big.NewRat(1, 100) 18 ratTen = big.NewRat(10, 1) 19 20 rat0 = big.NewRat(0, 1) 21 rat1 = big.NewRat(1, 10) 22 rat2 = big.NewRat(2, 10) 23 rat3 = big.NewRat(3, 10) 24 rat4 = big.NewRat(4, 10) 25 rat5 = big.NewRat(5, 10) 26 rat6 = big.NewRat(6, 10) 27 rat7 = big.NewRat(7, 10) 28 rat8 = big.NewRat(8, 10) 29 ratline = big.NewRat(9, 10) 30 ) 31 32 type lvlMath struct { 33 mu sync.Mutex 34 manure []*big.Int //store the used energy in one period 35 cycleLen int 36 lapWidth uint64 37 ydayAmt *big.Int 38 tdayAmt *big.Int 39 newest *big.Int //the gas wait to exec 40 height uint64 41 } 42 43 func newLvlMath(cycleLen int, lapWidth uint64) *lvlMath { 44 return &lvlMath{ 45 manure: make([]*big.Int, 0, cycleLen*2+1), 46 ydayAmt: big.NewInt(0), 47 tdayAmt: big.NewInt(0), 48 newest: big.NewInt(0), 49 cycleLen: cycleLen, 50 lapWidth: lapWidth, 51 height: 0, 52 } 53 } 54 55 func (this *lvlMath) pull(height uint64, usedGas *big.Int) bool { 56 this.mu.Lock() 57 defer this.mu.Unlock() 58 freshManure := big.NewInt(0).Set(usedGas) 59 this.newest.Add(this.newest, freshManure) 60 this.height = height 61 //fmt.Println("💊 💊 💊 ", height, this.lapWidth) 62 if height%this.lapWidth == 0 { 63 lapGas := new(big.Int).Set(this.newest) 64 this.newest.SetInt64(0) 65 this.manure = append(this.manure, lapGas) 66 l := len(this.manure) 67 if l <= this.cycleLen { 68 this.ydayAmt.Add(this.ydayAmt, lapGas) 69 } else if l <= this.cycleLen*2 { 70 this.tdayAmt.Add(this.tdayAmt, lapGas) 71 } else { 72 this.pop() 73 return true 74 } 75 } 76 return false 77 } 78 79 func (this *lvlMath) pop() { 80 if len(this.manure) == this.cycleLen*2+1 { 81 yRmoved := this.manure[0] 82 tRemoved := this.manure[this.cycleLen] 83 newest := this.manure[this.cycleLen*2] 84 this.manure = this.manure[1:] 85 this.ydayAmt.Sub(this.ydayAmt, yRmoved).Add(this.ydayAmt, tRemoved) 86 this.tdayAmt.Sub(this.tdayAmt, tRemoved).Add(this.tdayAmt, newest) 87 } 88 } 89 90 func (this *lvlMath) r() *big.Rat { 91 bt := new(big.Rat).SetInt(this.tdayAmt) 92 by := new(big.Rat).SetInt(this.ydayAmt) 93 rat := new(big.Rat) 94 rat.Sub(bt, by) 95 byInv := new(big.Rat).Set(by) 96 if byInv.Cmp(rat0) != 0 { 97 byInv.Inv(byInv) 98 } 99 rat.Mul(rat, byInv) 100 101 sign := true 102 if rat.Sign() == -1 { 103 sign = false 104 } 105 rat.Abs(rat) 106 if rat.Cmp(rat1) == -1 { 107 rat.Set(rat0) 108 109 } else if rat.Cmp(rat2) == -1 { 110 rat.Set(rat1) 111 } else if rat.Cmp(rat3) == -1 { 112 rat.Set(rat2) 113 } else if rat.Cmp(rat4) == -1 { 114 rat.Set(rat3) 115 } else if rat.Cmp(rat5) == -1 { 116 rat.Set(rat4) 117 } else if rat.Cmp(rat6) == -1 { 118 rat.Set(rat5) 119 } else if rat.Cmp(rat7) == -1 { 120 rat.Set(rat6) 121 } else if rat.Cmp(rat8) == -1 { 122 rat.Set(rat7) 123 } else if rat.Cmp(ratline) == -1 { 124 rat.Set(rat8) 125 } else { 126 rat.Set(ratline) 127 } 128 if !sign { 129 rat.Mul(rat, ratN) 130 } 131 return rat 132 } 133 134 func (this *lvlMath) m(rat *big.Rat) *big.Rat { 135 by := new(big.Rat).SetInt(this.ydayAmt) 136 m := new(big.Rat) 137 m.Add(ratX, rat) 138 m.Mul(m, by) 139 m.Mul(m, ratC) 140 if m.Cmp(minM) == -1 { 141 m.Set(minM) 142 } 143 return m 144 } 145 146 func (this *lvlMath) d(rat *big.Rat) []*big.Rat { 147 sign := rat.Sign() 148 d1 := new(big.Rat).Set(ratX) 149 factor := new(big.Rat) 150 if rat.Cmp(rat8) == 1 { 151 if sign == 1 { 152 factor.Set(dratMax) 153 } 154 } else { 155 d1.Set(ratX) 156 factor.Mul(dratL2, rat) 157 factor.Sub(dratL1, factor) 158 } 159 160 step := this.ratStep(rat) 161 ds := make([]*big.Rat, 0, step) 162 ds = append(ds, d1) 163 offset := 1 164 for i := lv2; i <= lv9; i++ { 165 if offset >= step { 166 break 167 } 168 dn := new(big.Rat).Add(ds[i-2], factor) 169 factor.Sub(factor, dratS) 170 ds = append(ds, dn) 171 offset++ 172 } 173 return ds 174 } 175 176 func (this *lvlMath) v(rat, m *big.Rat, dsReal []*big.Rat, distribution []*big.Int) []uint64 { 177 l := len(dsReal) 178 /*fmt.Println("dsreal", dsReal) 179 fmt.Println("distribution", distribution)*/ 180 lvAoumt := make([]*big.Rat, 0, l) 181 for i := 0; i < l; i++ { 182 //fmt.Println("lvamount", distribution[i]) 183 lvAoumt = append(lvAoumt, new(big.Rat).SetInt(distribution[i])) 184 } 185 deno := new(big.Rat) 186 for k, v := range dsReal { 187 part := new(big.Rat) 188 part.Mul(v, lvAoumt[k]) 189 //fmt.Println("deno add ", part, v, lvAoumt[k]) 190 deno.Add(deno, part) 191 } 192 //fmt.Println("deno", deno) 193 if deno.Cmp(rat0) != 0 { 194 deno.Inv(deno) 195 } 196 197 per := make([]uint64, 0, l) 198 for _, v := range dsReal { 199 part := new(big.Rat) 200 part.Mul(v, m) 201 part.Mul(part, deno) 202 part.Mul(part, ratU) 203 rfTmp := big.NewFloat(0).SetRat(part) 204 integer, _ := rfTmp.Uint64() 205 per = append(per, integer) 206 } 207 //fmt.Println("️ ", per) 208 return per 209 } 210 211 func (this *lvlMath) ratStep(rat *big.Rat) int { 212 sign := rat.Sign() 213 step := 9 214 if sign == 1 { 215 mid := new(big.Rat).Set(rat) 216 mid.Mul(ratTen, mid) 217 num, _ := mid.Float64() 218 step = step - int(num) 219 if step == 0 { 220 step = 1 221 } 222 return step 223 } else { 224 return step 225 } 226 } 227 228 func (this *lvlMath) reward(height uint64, energyUsed *big.Int, distribution []*big.Int) []uint64 { 229 bl := this.pull(height, energyUsed) 230 if bl { 231 r := this.r() 232 m := this.m(r) 233 //fmt.Println("💊 💊 💊 💊", m) 234 d := this.d(r) 235 return this.v(r, m, d, distribution) 236 } 237 //fmt.Println("📈 bl ", bl) 238 return make([]uint64, 0) 239 }