github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/store/mainchain/account_level/level_manager.go (about) 1 package account_level 2 3 import ( 4 "math/big" 5 "sync" 6 7 "github.com/sixexorg/magnetic-ring/errors" 8 9 "time" 10 11 "fmt" 12 13 "github.com/sixexorg/magnetic-ring/common" 14 "github.com/sixexorg/magnetic-ring/store/mainchain/states" 15 ) 16 17 type LvStatistic struct { 18 Count uint32 19 Amount *big.Int 20 } 21 22 func (this *LvStatistic) sub(num *big.Int) { 23 this.Amount.Sub(this.Amount, num) 24 this.Count-- 25 } 26 func (this *LvStatistic) add(num *big.Int) { 27 this.Amount.Add(this.Amount, num) 28 this.Count++ 29 } 30 31 var lmInstance *LevelManager 32 33 type LevelManager struct { 34 m sync.RWMutex 35 cycle uint64 36 height uint64 37 //number of account, amount distribution 38 distribution map[EasyLevel]*LvStatistic 39 nextAccLvl map[common.Address]*LvlAmount 40 math *lvlMath 41 //The levels change and need to be persisted to the database 42 lvlChange map[common.Address]EasyLevel 43 44 LevelStore *LevelStore 45 nextHeaderProperty []uint64 46 } 47 48 func NewLevelManager(cycle int, lapWidth uint64, dbDir string) (*LevelManager, error) { 49 db, err := NewLevelStore(dbDir) 50 if err != nil { 51 return nil, err 52 } 53 lm := &LevelManager{ 54 distribution: make(map[EasyLevel]*LvStatistic, 9), 55 nextAccLvl: make(map[common.Address]*LvlAmount), 56 lvlChange: make(map[common.Address]EasyLevel), 57 math: newLvlMath(cycle, lapWidth), 58 LevelStore: db, 59 } 60 61 for i := lv1; i <= lv9; i++ { 62 lm.distribution[i] = &LvStatistic{ 63 Amount: big.NewInt(0), 64 Count: 0, 65 } 66 } 67 return lm, nil 68 } 69 70 func (this *LevelManager) GetNextHeaderProperty(nextHeight uint64) ([]uint64, error) { 71 this.m.RLock() 72 defer this.m.RUnlock() 73 if nextHeight != this.height+1 { 74 return nil, errors.ERR_PARAM_NOT_VALID 75 } 76 FLAG: 77 if this.nextHeaderProperty == nil { 78 time.Sleep(time.Millisecond * 100) 79 goto FLAG 80 } 81 return this.nextHeaderProperty, nil 82 } 83 84 //ReceiveAccountStates is calculated the account level after the block is saved 85 func (this *LevelManager) ReceiveAccountStates(ass states.AccountStates, energyUesd *big.Int, height uint64) { 86 this.m.Lock() 87 defer this.m.Unlock() 88 this.height = height 89 this.execAccountStates(ass, height) 90 this.levelUpL() 91 this.generateReward(height, energyUesd) 92 } 93 94 var ( 95 zeroBInt = big.NewInt(0) 96 ) 97 98 func (this *LevelManager) execAccountStates(ass states.AccountStates, height uint64) { 99 for _, v := range ass { 100 fmt.Printf("🤵 ReceiveAccountStates account:%s height:%d balance:%d \n", v.Address.ToString(), v.Height, v.Data.Balance.Uint64()) 101 /* if k != 3 { 102 continue 103 }*/ 104 if height == 1 { 105 if v.Data.Balance.Cmp(lv9_b) != -1 { 106 this.genesisLevel9(v.Address, v.Data.Balance) 107 continue 108 } 109 } 110 key := v.Address 111 amount := v.Data.Balance 112 lvline := rankLevel(v.Data.Balance) 113 la := this.nextAccLvl[key] 114 115 // not exists 116 if la == nil { 117 //no change 118 if lvline == lv0 { 119 continue 120 } 121 //achieve lv 122 this.levelWillBe(key, lvline, amount) 123 continue 124 } 125 //already exists 126 im, l, _, cur := la.Lv.Decode() 127 //clear level 128 if lvline == 0 { 129 this.levelClear(key, cur, la.Amount) 130 continue 131 } 132 133 //new account is bigger 134 if lvline > l { 135 //bigger than next cur 136 if l == cur { 137 l++ 138 } 139 this.lvlUpdate(key, im, l, lvline) 140 //fmt.Println("等级", l-1, this.distribution[cur]) 141 this.distribution[cur].amountIncrease(amount, la.Amount) 142 this.amountUpdate(key, amount) 143 continue 144 } else if lvline == l { 145 //only amout update 146 this.distribution[cur].amountIncrease(amount, la.Amount) 147 this.amountUpdate(key, amount) 148 continue 149 } else if lvline < l { 150 //lvl down 151 this.levelDown(key, lvline, cur, amount, la.Amount) 152 this.amountUpdate(key, amount) 153 continue 154 } 155 } 156 } 157 158 func (this *LevelManager) generateReward(height uint64, energyUsed *big.Int) { 159 dis := this.getLvAmountDistribution() 160 rewards := this.math.reward(height, energyUsed, dis) 161 //fmt.Printf("🈲️ destroy:%d ,reward:%v\n", energyUsed.Uint64(), rewards) 162 this.nextHeaderProperty = rewards 163 } 164 func (this *LevelManager) getLvAmountDistribution() []*big.Int { 165 s := make([]*big.Int, 0, 9) 166 for i := lv1; i <= lv9; i++ { 167 s = append(s, big.NewInt(0).Set(this.distribution[i].Amount)) 168 } 169 return s 170 } 171 func (this *LevelManager) levelUpL() { 172 /* for j := EasyLevel(1); j <= lv9; j++ { 173 fmt.Printf("pre lv %d count:%d amount:%d \n", j, this.distribution[j].Count, this.distribution[j].Amount.Uint64()) 174 }*/ 175 for k, v := range this.nextAccLvl { 176 im, l, r, _ := v.Lv.Decode() 177 //nothing to do 178 if r == lv0 { 179 continue 180 } 181 if im { 182 //next level is the same as the level after next 183 this.levelUp(k, l+1, r, v.Amount) 184 continue 185 } else { 186 this.lvlUpdate(k, true, l, r) 187 continue 188 } 189 } 190 err := this.LevelStore.SaveLevels(this.height, this.lvlChange) 191 if err != nil { 192 panic(err) 193 } 194 this.lvlChange = make(map[common.Address]EasyLevel) 195 //fmt.Println("-------------------") 196 /* for j := EasyLevel(1); j <= lv9; j++ { 197 fmt.Printf("aft lv %d count:%d amount:%d \n", j, this.distribution[j].Count, this.distribution[j].Amount.Uint64()) 198 }*/ 199 } 200 201 func (this *LevelManager) levelWillBe(account common.Address, r EasyLevel, amount *big.Int) { 202 this.nextAccLvl[account] = &LvlAmount{ 203 Amount: amount, 204 Lv: newAccountLevel(false, lv1, r), 205 } 206 } 207 func (this *LevelManager) levelUp(account common.Address, l, r EasyLevel, amount *big.Int) { 208 if l > r && r != lv0 { 209 l = r 210 r = lv0 211 } 212 this.lvlUpdate(account, true, l, r) 213 curLv := l 214 if r == 0 { 215 curLv = l 216 } else { 217 curLv = l - 1 218 } 219 prevLv := curLv - 1 220 this.lvlChange[account] = curLv 221 this.lvlAmoutUpdate(curLv, prevLv, amount, amount) 222 } 223 224 func (this *LevelManager) levelDown(account common.Address, l, prevLv EasyLevel, amount, prevAmount *big.Int) { 225 this.lvlUpdate(account, true, l, 0) 226 this.lvlChange[account] = l 227 this.lvlAmoutUpdate(l, prevLv, amount, prevAmount) 228 } 229 230 func (this *LevelManager) levelClear(account common.Address, prevLv EasyLevel, prevAmount *big.Int) { 231 delete(this.nextAccLvl, account) 232 this.lvlChange[account] = lv0 233 this.lvlAmoutUpdate(lv0, prevLv, nil, prevAmount) 234 } 235 236 func (this *LevelManager) lvlUpdate(account common.Address, im bool, left, right EasyLevel) { 237 this.nextAccLvl[account].Lv = newAccountLevel(im, left, right) 238 } 239 func (this *LevelManager) amountUpdate(account common.Address, amount *big.Int) { 240 this.nextAccLvl[account].Amount.Set(amount) 241 } 242 func (this *LvStatistic) amountIncrease(amount, prevAmount *big.Int) { 243 if this != nil { 244 //fmt.Println(1, this.Amount.Uint64(), amount.Uint64()) 245 this.Amount.Add(this.Amount, amount) 246 //fmt.Println(2, this.Amount.Uint64(), prevAmount.Uint64()) 247 this.Amount.Sub(this.Amount, prevAmount) 248 //fmt.Println(3, this.Amount.Uint64()) 249 } 250 } 251 252 func (this *LevelManager) lvlAmoutUpdate(curLv, prevLv EasyLevel, amount, prevAmount *big.Int) { 253 if curLv > lv0 { 254 this.distribution[curLv].add(amount) 255 } 256 if prevLv > lv0 { 257 this.distribution[prevLv].sub(prevAmount) 258 } 259 } 260 261 func (this *LevelManager) genesisLevel9(acc common.Address, amount *big.Int) { 262 this.distribution[lv9].Count++ 263 this.distribution[lv9].add(amount) 264 this.nextAccLvl[acc] = &LvlAmount{ 265 Amount: amount, 266 Lv: newAccountLevel(true, lv9, 0), 267 } 268 this.lvlChange[acc] = lv9 269 }