github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/store/mainchain/validation/state_validate_league.go (about) 1 package validation 2 3 import ( 4 "fmt" 5 6 "github.com/sixexorg/magnetic-ring/common" 7 "github.com/sixexorg/magnetic-ring/errors" 8 "github.com/sixexorg/magnetic-ring/store/mainchain/states" 9 "github.com/sixexorg/magnetic-ring/store/mainchain/storages" 10 ) 11 12 func (s *StateValidate) VerifyLeague(oplogs []*OpLog) (opIndes []int, err error) { 13 opIndes = make([]int, 0, len(oplogs)) 14 for k, v := range oplogs { 15 opTmp := v 16 err = s.verifyLeague(opTmp) 17 if err == nil { 18 //already exec 19 opIndes = append(opIndes, k) 20 } else { 21 break 22 } 23 } 24 return opIndes, err 25 } 26 27 //verifyLeague is check leagueState and memberState 28 //in league 29 func (s *StateValidate) verifyLeague(oplog *OpLog) error { 30 s.M.Lock() 31 defer s.M.Unlock() 32 { 33 if oplog.method < LeagueMaxLine && oplog.method > LeagueMinLine { 34 switch oplog.method { 35 case League_create: 36 modelCreate := oplog.data.(*OPCreateLeague) 37 err := s.ContainsLeague(modelCreate.League, modelCreate.Symbol) 38 if err != nil { 39 return err 40 } 41 leagueState := &states.LeagueState{ 42 Address: modelCreate.League, 43 Height: s.TargetHeight, 44 Symbol: modelCreate.Symbol, 45 MinBox: modelCreate.Minbox, 46 Creator: modelCreate.Creator, 47 Rate: modelCreate.Rate, 48 Private: modelCreate.Private, 49 Data: &states.League{ 50 Nonce: 1, 51 FrozenBox: modelCreate.FrozenBox, 52 MemberRoot: common.Hash{}, //todo merkle root 53 54 }, 55 } 56 s.DirtyLeagueState[leagueState.Address] = leagueState 57 s.AppendLeagueForCreate(modelCreate.TxHash, leagueState.Address) 58 return nil 59 case League_member_apply, League_member_add: 60 opaa := oplog.data.(*OPAddressAdress) 61 err := s.getLeagueState(opaa.Second) 62 fmt.Printf("🔆 verifyLeague p1 leagueId:%s account:%s %v\n", opaa.Second.ToString(), opaa.First.ToString(), s.DirtyLMemberState[opaa.Second][opaa.First]) 63 if err != nil { 64 //fmt.Printf("🔆 verifyLeague err1 %v\n", err) 65 return err 66 } 67 //TODO Verify that the league exists,and coherence of state 68 bl, st := s.getMemberCondition(opaa.Second, opaa.First, oplog.method) 69 if !bl { 70 fmt.Println("🔆 verifyLeague err2") 71 return errors.ERR_STATE_MEMBER_ILLEGAL_STATUS 72 } 73 if s.DirtyLMemberState[opaa.Second] == nil { 74 s.DirtyLMemberState[opaa.Second] = make(map[common.Address]*states.LeagueMember) 75 } 76 if s.DirtyLMemberState[opaa.Second][opaa.First] == nil { 77 s.DirtyLMemberState[opaa.Second][opaa.First] = &states.LeagueMember{ 78 LeagueId: opaa.Second, 79 Height: s.TargetHeight, 80 Data: &states.LeagueAccount{ 81 Account: opaa.First, 82 Status: st, 83 }, 84 } 85 fmt.Printf("🔆 verifyLeague p2 %v\n", s.DirtyLMemberState[opaa.Second][opaa.First]) 86 return nil 87 } 88 return errors.ERR_STATE_LEAGUE_ONCE 89 case League_member_remove: 90 opaa := oplog.data.(*OPAddressAdress) 91 err := s.getLeagueState(opaa.Second) 92 //fmt.Printf("🔆 verifyLeague p1 leagueId:%s account:%s %v\n", opaa.Second.ToString(), opaa.First.ToString(), s.DirtyLMemberState[opaa.Second][opaa.First]) 93 if err != nil { 94 return err 95 } 96 bl := s.getMemberRecycleMinbox(opaa.Second, opaa.First) 97 if !bl { 98 //fmt.Println("🔆 verifyLeague err2") 99 return errors.ERR_STATE_MEMBER_ILLEGAL_STATUS 100 } 101 if s.DirtyLMemberState[opaa.Second] == nil { 102 s.DirtyLMemberState[opaa.Second] = make(map[common.Address]*states.LeagueMember) 103 } 104 if s.DirtyLMemberState[opaa.Second][opaa.First] == nil { 105 s.DirtyLMemberState[opaa.Second][opaa.First] = &states.LeagueMember{ 106 LeagueId: opaa.Second, 107 Height: s.TargetHeight, 108 Data: &states.LeagueAccount{ 109 Account: opaa.First, 110 Status: states.LAS_Exit, 111 }, 112 } 113 fmt.Printf("🔆 verifyLeague p3 %v\n", s.DirtyLMemberState[opaa.Second][opaa.First]) 114 return nil 115 } 116 return errors.ERR_STATE_LEAGUE_ONCE 117 case League_minbox: 118 opaa := oplog.data.(*OPAddressUint64) 119 err := s.getLeagueState(opaa.Address) 120 if err != nil { 121 return err 122 } 123 if s.MemoLeagueState[opaa.Address].MinBox != opaa.Num { 124 return errors.ERR_LEAGUE_MINBOX_DIFF 125 } 126 return nil 127 /*case League_nonce_add: 128 an := oplog.data.(*OPAddressUint64) 129 err := s.getLeagueState(an.Address) 130 if err != nil { 131 return err 132 } 133 thisNonce := s.DirtyLeagueState[an.Address].Data.Nonce 134 if thisNonce+1 == an.Num { 135 s.DirtyLeagueState[an.Address].Data.Nonce = an.Num 136 return nil 137 } else if thisNonce+1 < an.Num { 138 return errors.ERR_STATE_LEAGUE_NONCE_BIGGER 139 } 140 return errors.ERR_STATE_LEAGUE_NONCE_DISCONTINUITY*/ 141 case League_raise: 142 an := oplog.data.(*OPAddressBigInt) 143 err := s.getLeagueState(an.Address) 144 if err != nil { 145 return err 146 } 147 return nil 148 149 } 150 } 151 return nil 152 } 153 } 154 func (s *StateValidate) RollbackLeague(oplogs []*OpLog, opIndes []int) { 155 for _, v := range opIndes { 156 s.rollbackLeague(oplogs[v]) 157 } 158 } 159 func (s *StateValidate) rollbackLeague(oplog *OpLog) { 160 s.M.Lock() 161 defer s.M.Unlock() 162 { 163 if oplog.method == League_create { 164 modelCreate := oplog.data.(*OPCreateLeague) 165 s.RemoveElementInLeagueForCreate(modelCreate.League) 166 } else if oplog.method == League_member_add || oplog.method == League_member_apply { 167 aa := oplog.data.(*OPAddressAdress) 168 s.DirtyLMemberState[aa.Second][aa.First] = nil 169 } 170 } 171 } 172 173 func (s *StateValidate) getLeagueState(address common.Address) error { 174 if s.DirtyAccountState[address] != nil { 175 return nil 176 } 177 as, err := s.ledgerStore.GetLeagueByHeight(s.TargetHeight-1, address) 178 if err != nil { 179 return err 180 } 181 fmt.Println("☀️ getLeagueState ", as.Address.ToString(), as.Rate, as.Data.FrozenBox.Uint64()) 182 as.Height = s.TargetHeight 183 asDirty := &states.LeagueState{} 184 common.DeepCopy(&asDirty, as) 185 s.MemoLeagueState[address] = as 186 s.DirtyLeagueState[address] = asDirty 187 return nil 188 } 189 func (s *StateValidate) getMemberCondition(leagueId, account common.Address, method opCode) (bool, states.LeagueAccountStatus) { 190 if method == League_member_apply { 191 //fmt.Printf("🔆 getMemberCondition p1 \n") 192 return s.getMemberApply(leagueId, account) 193 } else if method == League_member_add { 194 //fmt.Printf("🔆 getMemberCondition p2 \n") 195 return s.getMemberAdd(leagueId, account) 196 } 197 return false, states.LAS_Apply 198 } 199 200 func (s *StateValidate) getMemberApply(leagueId, account common.Address) (bool, states.LeagueAccountStatus) { 201 memberState, err := s.ledgerStore.GetLeagueMemberByHeight(s.TargetHeight-1, leagueId, account) 202 isPrivate := s.MemoLeagueState[leagueId].IsPrivate() 203 if err == errors.ERR_DB_NOT_FOUND || memberState.Data.Status == states.LAS_Exit { 204 if isPrivate { 205 return true, states.LAS_Apply 206 } else { 207 return true, states.LAS_Normal 208 } 209 } 210 return false, states.LAS_Exit 211 } 212 func (s *StateValidate) getMemberAdd(leagueId, account common.Address) (bool, states.LeagueAccountStatus) { 213 isPrivate := s.MemoLeagueState[leagueId].IsPrivate() 214 //fmt.Printf("🔆 getMemberAdd p1 %v\n", isPrivate) 215 if !isPrivate { 216 return false, states.LAS_Apply 217 } 218 memberState, err := s.ledgerStore.GetLeagueMemberByHeight(s.TargetHeight-1, leagueId, account) 219 //fmt.Printf("🔆 getMemberAdd p2 %v %v\n", memberState, err) 220 if err != nil { 221 return false, states.LAS_Apply 222 } 223 if memberState.Data.Status == states.LAS_Apply { 224 return true, states.LAS_Normal 225 } 226 return false, states.LAS_Exit 227 } 228 func (s *StateValidate) getMemberRecycleMinbox(leagueId, account common.Address) bool { 229 isPrivate := s.MemoLeagueState[leagueId].IsPrivate() 230 if !isPrivate { 231 return false 232 } 233 memberState, err := s.ledgerStore.GetLeagueMemberByHeight(s.TargetHeight-1, leagueId, account) 234 //fmt.Printf("🔆 getMemberAdd p2 %v %v\n", memberState, err) 235 if err != nil { 236 return false 237 } 238 if memberState.Data.Status == states.LAS_Apply { 239 return true 240 } 241 return false 242 } 243 244 func (s *StateValidate) AppendLeagueForCreate(txHash common.Hash, address common.Address) { 245 s.LeagueForCreate = append(s.LeagueForCreate, &storages.LeagueKV{address, txHash}) 246 } 247 func (s *StateValidate) checkSymbol(symbol common.Symbol) error { 248 if _, ok := s.SymbolForCreate[symbol]; ok { 249 return errors.ERR_STATE_SYMBOL_EXISTS 250 } 251 err := s.ledgerStore.SymbolExists(symbol) 252 if err != nil { 253 return err 254 } 255 s.SymbolForCreate[symbol] = struct{}{} 256 return nil 257 } 258 func (s *StateValidate) ContainsLeague(address common.Address, symbol common.Symbol) error { 259 for _, v := range s.LeagueForCreate { 260 if address == v.K { 261 return errors.ERR_STATE_LEAGUE_EXISTS 262 } 263 } 264 err := s.checkSymbol(symbol) 265 if err != nil { 266 return err 267 } 268 return nil 269 }