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))
예제 #2
0
    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))