github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/store/orgchain/validation/state_validate_bonus.go (about) 1 package validation 2 3 import ( 4 "math/big" 5 6 "github.com/sixexorg/magnetic-ring/common" 7 "github.com/sixexorg/magnetic-ring/core/orgchain/types" 8 "github.com/sixexorg/magnetic-ring/errors" 9 "github.com/sixexorg/magnetic-ring/store/orgchain/storages" 10 "github.com/sixexorg/magnetic-ring/store/storelaw" 11 ) 12 13 //just sub balance 14 func (s *StateValidate) verifyBonus(oplog *OpLog) (extra []*OpLog, err error) { 15 if oplog.method == Account_bonus_fee { 16 aa := oplog.data.(*OPAddressBigInt) 17 s.getAccountState(aa.Address) 18 amount, bonusHeight, err := calculateReward(s.ledgeror, aa.Address, s.leagueId, s.MemoAccountState[aa.Address].BonusHeight(), s.currentBlockHeight) 19 //s.calculateReward(aa.Address, s.MemoAccountState[aa.Address].BonusHeight()) 20 if err != nil { 21 return nil, err 22 } 23 if amount.Cmp(aa.Num) == -1 { 24 return nil, errors.ERR_STATE_BONUS_NOT_ENOUGH 25 } 26 amount.Sub(amount, aa.Num) 27 ops := analysisBonusAfter(aa.Address, bonusHeight, amount) 28 return ops, nil 29 30 } 31 return nil, nil 32 } 33 34 func (s *StateValidate) calculateReward(account common.Address, bonusLeft uint64) (amount *big.Int, bonusHeight uint64, err error) { 35 bonusLeft = bonusLeft + types.HWidth 36 // get account state between bonusHeight+1 and s.targetHeight 37 // get headlvs 38 // get height level of account 39 ass, err := s.ledgeror.GetAccountRange(bonusLeft, s.currentBlockHeight, account, s.leagueId) 40 if err != nil { 41 return nil, 0, err 42 } 43 as, _ := s.ledgeror.GetPrevAccount4V(bonusLeft, account, s.leagueId) 44 if ass.Len() > 0 { 45 if as.GetHeight() < ass[0].GetHeight() { 46 ass = append(storelaw.AccountStaters{as}, ass...) 47 } 48 } else { 49 ass = storelaw.AccountStaters{as} 50 } 51 assFTree := make([]common.FTreer, 0, len(ass)) 52 for _, v := range ass { 53 assFTree = append(assFTree, v) 54 } 55 hbonus := s.ledgeror.GetBonus(s.leagueId) 56 amount, bonusHeight = aggregateBonus(assFTree, hbonus, bonusLeft, s.currentBlockHeight, types.HWidth) 57 return 58 } 59 60 func aggregateBonus(assFTree []common.FTreer, hbonus map[uint64]uint64, start, end, lapWidth uint64) (amount *big.Int, bonusLeft uint64) { 61 if start == 0 { 62 start += lapWidth 63 } 64 l := (end-start)/lapWidth + 1 65 balances := make([]*big.Int, 0, l) 66 aft := common.NewForwardTree(lapWidth, start, end, assFTree) 67 for !aft.Next() { 68 balances = append(balances, aft.Val().(*big.Int)) 69 } 70 sum := big.NewInt(0) 71 sp := big.NewInt(0) 72 for _, v := range balances { 73 sp.Mul(v, new(big.Int).SetUint64(hbonus[start])) 74 sum.Add(sum, sp) 75 bonusLeft = start 76 start += lapWidth 77 sp.SetUint64(0) 78 } 79 sum.Div(sum, bigU) 80 return sum, bonusLeft 81 } 82 func CalculateBonus(ledger *storages.LedgerStoreImp, account, leagueId common.Address) (amount *big.Int, bonusHeight uint64, err error) { 83 curHeight := ledger.GetCurrentBlockHeight() 84 as, err := ledger.GetPrevAccount4V(curHeight, account, leagueId) 85 if err != nil { 86 return nil, 0, err 87 } 88 return calculateReward(ledger, account, leagueId, as.BonusHeight(), curHeight) 89 } 90 func calculateReward(ledger storelaw.Ledger4Validation, account, leagueId common.Address, bonusLeft, curHeight uint64) (amount *big.Int, bonusHeight uint64, err error) { 91 bonusLeft = bonusLeft + types.HWidth 92 // get account state between bonusHeight+1 and s.targetHeight 93 // get headlvs 94 // get height level of account 95 ass, err := ledger.GetAccountRange(bonusLeft, curHeight, account, leagueId) 96 if err != nil { 97 return nil, 0, err 98 } 99 as, _ := ledger.GetPrevAccount4V(bonusLeft, account, leagueId) 100 if ass.Len() > 0 { 101 if as.GetHeight() < ass[0].GetHeight() { 102 ass = append(storelaw.AccountStaters{as}, ass...) 103 } 104 } else { 105 ass = storelaw.AccountStaters{as} 106 } 107 assFTree := make([]common.FTreer, 0, len(ass)) 108 for _, v := range ass { 109 assFTree = append(assFTree, v) 110 } 111 hbonus := ledger.GetBonus(leagueId) 112 amount, bonusHeight = aggregateBonus(assFTree, hbonus, bonusLeft, curHeight, types.HWidth) 113 return 114 }