def check_valid(self, store): """Determines if the transaction is valid. Args: store (dict): Transaction store mapping. """ # Name (of the game) is always required if self._name is None or self._name == '': raise InvalidTransaction('name not set') # Action is always required if self._action is None or self._action == '': raise InvalidTransaction('action not set') # The remaining validity rules depend upon which action has # been specified. if self._action == 'CREATE': if self._name in store: raise InvalidTransaction('game already exists') # Restrict game name letters and numbers. if not re.match("^[a-zA-Z0-9]*$", self._name): raise InvalidTransaction( "Only letters a-z A-Z and numbers 0-9 are allowed in " "the game name!") elif self._action == 'JOIN': # Check that self._name is in the store (to verify # that the game exists (see FIRE below). if self._name not in store: raise InvalidTransaction( 'Trying to join a game that does not exist') state = store[self._name]['State'] if state != "NEW": # Check that the game can be joined (the state is 'NEW') raise InvalidTransaction( 'The game cannot accept any new participant') # Check that the game board is the right size (10x10) if len(self._board) != self._size: raise InvalidTransaction('Game board is not valid size') for row in range(0, self._size): if len(self._board[row]) != self._size: raise InvalidTransaction('Game board is not valid size') # Validate that self._board contains hash-like strings for row in range(0, self._size): for col in range(0, self._size): # length of sha512 hexdigest is 32 characters if len(self._board[row][col]) != 128: raise InvalidTransaction("invalid board hash") elif self._action == 'FIRE': if self._name not in store: raise InvalidTransaction('no such game') if self._column is None: raise InvalidTransaction("Column is required") if self._row is None: raise InvalidTransaction("Row is required") # Check that self._column is valid (letter from A-J) if not any((c in self._acceptable_columns) for c in self._column): raise InvalidTransaction( 'Acceptable columns letters are A to J') # Check that self._row is valid (number from 1-10) try: row = int(self._row) if (row < 1) or (row > 10): raise InvalidTransaction( 'Acceptable rows numbers are 1 to 10') except ValueError: raise InvalidTransaction('Acceptable rows numbers are 1 to 10') state = store[self._name]['State'] if state in ['P1-WIN', 'P2-WIN']: raise InvalidTransaction('game complete') if state == 'NEW': raise InvalidTransaction("Game doesn't have enough players.") player = None if state == 'P1-NEXT': player1_firing = True player = store[self._name]['Player1'] if player != self._signer_public_key: raise InvalidTransaction('invalid player 1') elif state == 'P2-NEXT': player1_firing = False player = store[self._name]['Player2'] if player != self._signer_public_key: raise InvalidTransaction('invalid player 2') else: raise InvalidTransaction("invalid state: {}".format(state)) # Check whether the board's column and row have already been # fired upon. if player1_firing: target_board = store[self._name]['TargetBoard1'] else: target_board = store[self._name]['TargetBoard2'] firing_row = int(self._row) - 1 firing_column = ord(self._column) - ord('A') if target_board[firing_row][firing_column] != '?': raise InvalidTransaction( "{} {} has already been fired upon".format( self._column, self._row)) # Make sure a space is revealed if it isn't the first turn. if 'LastFireColumn' in store[self._name]: if self._reveal_space is None or self._reveal_nonce is None: raise InvalidTransaction( "Attempted to fire without revealing target") if state == 'P1-NEXT': hashed_board = 'HashedBoard1' else: hashed_board = 'HashedBoard2' col = ord(store[self._name]['LastFireColumn']) - ord('A') row = int(store[self._name]['LastFireRow']) - 1 hashed_space = hash_space(self._reveal_space, self._reveal_nonce) if store[self._name][hashed_board][row][col] != hashed_space: raise InvalidTransaction( "Hash mismatch on reveal: {} != {}".format( store[self._name][hashed_board][row][col], hashed_space)) else: raise InvalidTransaction('invalid action: {}'.format(self._action))
def check_valid(self, store): """Determines if the transaction is valid. Args: store (dict): Transaction store mapping. """ super(BattleshipTransaction, self).check_valid(store) LOGGER.debug('checking %s', str(self)) # Name (of the game) is always required if self._name is None or self._name == '': raise InvalidTransactionError('name not set') # Action is always required if self._action is None or self._action == '': raise InvalidTransactionError('action not set') # The remaining validity rules depend upon which action has # been specified. if self._action == 'CREATE': if self._name in store: raise InvalidTransactionError('game already exists') # Restrict game name letters and numbers. if not re.match("^[a-zA-Z0-9]*$", self._name): raise InvalidTransactionError( "Only letters a-z A-Z and numbers 0-9 are allowed in " "the game name!") elif self._action == 'JOIN': # Check that self._name is in the store (to verify # that the game exists (see FIRE below). state = store[self._name]['State'] LOGGER.info("state: %s", state) if self._name not in store: raise InvalidTransactionError( 'Trying to join a game that does not exist') elif state != "NEW": # Check that the game can be joined (the state is 'NEW') raise InvalidTransactionError( 'The game cannot accept any new participant') # Check that the game board is the right size (10x10) if len(self._board) != self._size: raise InvalidTransactionError('Game board is not valid size') for row in xrange(0, self._size): if len(self._board[row]) != self._size: raise InvalidTransactionError( 'Game board is not valid size') # Validate that self._board contains hash-like strings for row in xrange(0, self._size): for col in xrange(0, self._size): # length of md5 hexdigest is 32 characters if len(self._board[row][col]) != 32: raise InvalidTransactionError("invalid board hash") elif self._action == 'FIRE': if self._name not in store: raise InvalidTransactionError('no such game') if self._column is None: raise InvalidTransactionError("Column is required") if self._row is None: raise InvalidTransactionError("Row is required") # Check that self._column is valid (letter from A-J) if not any((c in self._acceptable_columns) for c in self._column): raise InvalidTransactionError( 'Acceptable columns letters are A to J') # Check that self._row is valid (number from 1-10) try: row = int(self._row) if (row < 1) or (row > 10): raise InvalidTransactionError( 'Acceptable rows numbers are 1 to 10') except ValueError: raise InvalidTransactionError( 'Acceptable rows numbers are 1 to 10') state = store[self._name]['State'] if state in ['P1-WIN', 'P2-WIN']: raise InvalidTransactionError('game complete') if state == 'NEW': raise InvalidTransactionError( "Game doesn't have enough players.") player = None if state == 'P1-NEXT': player1_firing = True player = store[self._name]['Player1'] if player != self.OriginatorID: raise InvalidTransactionError('invalid player 1') elif state == 'P2-NEXT': player1_firing = False player = store[self._name]['Player2'] if player != self.OriginatorID: raise InvalidTransactionError('invalid player 2') else: raise InvalidTransactionError( "invalid state: {}".format(state)) # Check whether the board's column and row have already been # fired upon. if player1_firing: target_board = store[self._name]['TargetBoard1'] else: target_board = store[self._name]['TargetBoard2'] firing_row = int(self._row) - 1 firing_column = ord(self._column) - ord('A') if target_board[firing_row][firing_column] != '?': raise InvalidTransactionError( "{} {} has already been fired upon".format( self._column, self._row) ) # Make sure a space is revealed if it isn't the first turn. if 'LastFireColumn' in store[self._name]: if self._reveal_space is None or self._reveal_nonce is None: raise InvalidTransactionError( "Attempted to fire without revealing target") if state == 'P1-NEXT': hashed_board = 'HashedBoard1' else: hashed_board = 'HashedBoard2' col = ord(store[self._name]['LastFireColumn']) - ord('A') row = int(store[self._name]['LastFireRow']) - 1 hashed_space = hash_space(self._reveal_space, self._reveal_nonce) if store[self._name][hashed_board][row][col] != hashed_space: raise InvalidTransactionError( "Hash mismatch on reveal: {} != {}".format( hashed_board[row][col], hashed_space)) else: raise InvalidTransactionError( 'invalid action: {}'.format(self._action))