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  }