Exemplo n.º 1
0
    def check_valid(self, store, txn):
        """
        Verify the validity of the update

        Args:
            store: The local store for bond transactions
            txn: Ignored

        Returns:
            Nothing

        Throws InvalidTransactionError if not valid.
        """
        LOGGER.debug('checking %s', str(self))

        # A LIBOR transaction requires the following:
        # 1. The update must be signed by a well-known key.  Currently this key
        #    has been generated by us, but eventually it is hoped to be the
        #    private counterpart to a public key published by the organization
        #    that provides the LIBORs.
        if self.__libor_object__.Signature is None:
            raise InvalidTransactionError('LIBOR data has not been signed')
        if not self.__libor_object__.verify_signature(
                self.__LIBOR_PUBLISHER_ADDR__):
            raise InvalidTransactionError(
                'Key used to sign LIBOR data does not match publisher')

        # 2. The date must be present, must be in IOS-8601 format, and may not
        #    be a date in the future.
        if self.__libor_object__.date is None:
            raise InvalidTransactionError('Date is not set')

        # Try to convert the date from an ISO-8601 string ("YYYY-MM-DD") to
        # a date object.  An exception indicates that the format is invalid.
        try:
            the_date = \
                datetime.strptime(
                    self.__libor_object__.date,
                    "%Y-%m-%d").date()
        except TypeError:
            raise InvalidTransactionError(
                'Date value <{}> must be a string value'.format(
                    self.__libor_object__.date))
        except ValueError:
            raise InvalidTransactionError(
                'Date <{}> is invalid or not in YYYY-MM-DD format'.format(
                    self.__libor_object__.date))

        if the_date > datetime.utcnow().date():
            raise InvalidTransactionError(
                'Date <{0}> is in the future.  Today is <{1}>.'.format(
                    the_date.isoformat(),
                    datetime.utcnow().date().isoformat()))

        # 3. The data must not already be in the store (i.e., rates have
        #    not already been submitted for this date by some validator).
        if self._object_id in store:
            raise InvalidTransactionError(
                'Rates have already been set for {}'.format(
                    self.__libor_object__.date))

        # 4. Each rate must not be NaN
        for maturity, rate in self.__libor_object__.rates.items():
            if math.isnan(rate):
                raise InvalidTransactionError(
                    '{} maturity does not contain a valid rate'.format(
                        maturity))
Exemplo n.º 2
0
    def postmsg(self, msgtype_name, info):
        """
        Post a transaction message to the validator, parse the returning CBOR
        and return the corresponding dictionary.
        """

        data = _dict2cbor(info)
        datalen = len(data)
        url = urlparse.urljoin(self._base_url, msgtype_name)

        LOGGER.debug('post transaction to %s with DATALEN=%d, DATA=<%s>', url,
                     datalen, data)

        try:
            request = urllib2.Request(url, data, {
                'Content-Type': 'application/cbor',
                'Content-Length': datalen
            })

            if self._cookie:
                request.add_header('cookie', self._cookie)

            opener = urllib2.build_opener(self._proxy_handler)
            response = opener.open(request, timeout=10)
            if not self._cookie:
                self._cookie = response.headers.get('Set-Cookie')
        except urllib2.HTTPError as err:
            content = err.read()
            if content is not None:
                headers = err.info()
                encoding = headers.get('Content-Type')

                if encoding == 'application/json':
                    value = _json2dict(content)
                elif encoding == 'application/cbor':
                    value = _cbor2dict(content)
                else:
                    LOGGER.warn('operation failed with response: %s', err.code)
                    raise MessageException(
                        'operation failed with response: {0}'.format(err.code))
                LOGGER.warn('operation failed with response: %s %s', err.code,
                            str(value))
                if "errorType" in value:
                    if value['errorType'] == "InvalidTransactionError":
                        raise InvalidTransactionError(
                            value['error'] if 'error' in value else value)
                    else:
                        raise MessageException(str(value))
            else:
                raise MessageException(
                    'operation failed with response: {0}'.format(err.code))
        except urllib2.URLError as err:
            LOGGER.warn('operation failed: %s', err.reason)
            raise MessageException('operation failed: {0}'.format(err.reason))

        except:
            LOGGER.warn('no response from server')
            raise MessageException('no response from server')

        content = response.read()
        headers = response.info()
        response.close()

        encoding = headers.get('Content-Type')

        if encoding == 'application/json':
            value = _json2dict(content)
        elif encoding == 'application/cbor':
            value = _cbor2dict(content)
        else:
            LOGGER.info('server responds with message %s of type %s', content,
                        encoding)
            return None

        LOGGER.debug(_pretty_print_dict(value))
        return value
Exemplo n.º 3
0
    def check_valid(self, store):
        """Determines if the transaction is valid.

        Args:
            store (dict): Transaction store mapping.
        """

        super(XoTransaction, self).check_valid(store)

        LOGGER.debug('checking %s', str(self))

        if self._name is None or self._name == '':
            raise InvalidTransactionError('name not set')

        if self._action is None or self._action == '':
            raise InvalidTransactionError('action not set')

        if self._action == 'CREATE':
            if self._name in store:
                raise InvalidTransactionError('game already exists')
        elif self._action == 'TAKE':
            if self._space is None:
                raise InvalidTransactionError('TAKE requires space')

            if self._space < 1 or self._space > 9:
                raise InvalidTransactionError('invalid space')

            if self._name not in store:
                raise InvalidTransactionError('no such game')

            state = store[self._name]['State']
            if state in ['P1-WIN', 'P2-WIN', 'TIE']:
                raise InvalidTransactionError('game complete')

            if state == 'P1-NEXT' and 'Player1' in store[self._name]:
                player1 = store[self._name]['Player1']
                if player1 != self.OriginatorID:
                    raise InvalidTransactionError('invalid player 1')

            if state == 'P2-NEXT' and 'Player2' in store[self._name]:
                player1 = store[self._name]['Player2']
                if player1 != self.OriginatorID:
                    raise InvalidTransactionError('invalid player 2')

            if store[self._name]['Board'][self._space - 1] != '-':
                raise InvalidTransactionError('space already taken')
        else:
            raise InvalidTransactionError('invalid action')
Exemplo n.º 4
0
    def check_valid(self, store, txn):
        # Verify that creator exists
        try:
            store.lookup('participant:key-id', txn.OriginatorID)
        except KeyError:
            raise InvalidTransactionError("Creator was not found : {}".format(
                txn.OriginatorID))

        if self._object_id in store:
            raise InvalidTransactionError(
                "Object with id already exists: {}".format(self._object_id))

        try:
            store.lookup('organization:name', self._name)
            raise InvalidTransactionError(
                "Object with name already exists: {}".format(self._name))
        except KeyError:
            pass

        if self._ticker is not None:
            try:
                store.lookup('organization:ticker', self._ticker)
                raise InvalidTransactionError(
                    "Object with ticker already exists: {}".format(
                        self._ticker))
            except KeyError:
                pass

        if self._pricing_source is not None:
            if len(self._pricing_source) != 4:
                raise InvalidTransactionError(
                    "Pricing source must be a four-character string: {}".
                    format(self._pricing_source))

            try:
                store.lookup('organization:pricing-source',
                             self._pricing_source)
                raise InvalidTransactionError(
                    "Object with pricing source already exists: {}".format(
                        self._pricing_source))
            except KeyError:
                pass

        if self._authorization is not None:
            for participant in self._authorization:
                if len(participant) != 2:
                    raise InvalidTransactionError(
                        "Must contain ParticpantId and Role for each entry"
                        " in Authorization: {}".format(participant))
                try:
                    participant_id = participant["ParticipantId"]
                    role = participant["Role"]

                except KeyError:
                    raise InvalidTransactionError(
                        "Must contain ParticipantId and Role for each entry"
                        " in Authorization: {}".format(participant))

                if role != "marketmaker" and role != "trader":
                    raise InvalidTransactionError(
                        "Role must be either "
                        "marketmaker or trader: {}".format(role))
                try:
                    store.get(participant_id, object_type='participant')
                except KeyError:
                    raise InvalidTransactionError(
                        "No such participant: {}".format(
                            participant['ParticipantId']))
Exemplo n.º 5
0
 def check_valid(self, store, txn):
     if not market_place_object_update.global_is_permitted(
             store, txn, self._creator_id, self.CreatorType):
         raise InvalidTransactionError(
             "Creator address not the same as txn.OriginatorID")
Exemplo n.º 6
0
    def check_valid(self, store):
        super(RPSTransaction, self).check_valid(store)

        logger.debug('checking %s', str(self))

        if self._name is None or self._name == '':
            raise InvalidTransactionError('name not set')

        if self._action is None or self._action == '':
            raise InvalidTransactionError('action not set')

        if self._action == 'CREATE':
            if self._name in store:
                raise InvalidTransactionError('game already exists')
            if (not isinstance(self._players, (int, long)) or not
                    self._players > 0):
                raise InvalidTransactionError(
                    'players must be a positive integer larger then 0: %s '
                    '(%s)' % (self._players, type(self._players)))
        elif self._action == 'SHOOT':
            if self._hand is None:
                raise InvalidTransactionError('SHOOT requires hand')

            if self._hand not in VALID_HANDS:
                raise InvalidTransactionError('invalid hand')

            if self._name not in store:
                raise InvalidTransactionError('no such game')

            players = store[self._name]['Players']
            state = store[self._name]['State']
            if state == 'COMPLETE':
                raise InvalidTransactionError('game complete')
            elif len(store[self._name]['Hands']) >= players:
                raise InvalidTransactionError(
                    'all players shown their hand but game state not set to '
                    'complete')
            elif state == 'OPEN':
                recorded_hand = store[self._name]['Hands']\
                    .get(self.OriginatorID)
                if recorded_hand is not None:
                    raise InvalidTransactionError('hand already registered')
            else:
                raise InvalidTransactionError('invalid game state')
        else:
            raise InvalidTransactionError('invalid action')
Exemplo n.º 7
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))
Exemplo n.º 8
0
    def apply(self, store):
        """Applies all the updates in the transaction to the transaction
        store.

        Args:
            store (dict): Transaction store mapping.
        """
        LOGGER.debug('apply %s', str(self))

        if self._action == 'CREATE':
            store[self._name] = {'State': 'NEW', 'Ships': self._ships}
        elif self._action == 'JOIN':
            game = store[self._name].copy()

            # If this is the first JOIN, set HashedBoard1 and Player1 in the
            # store.  if this is the second JOIN, set HashedBoard2 and
            # Player2 in the store.  Also, initialize TargetBoard1 and
            # TargetBoard2 as empty.
            if 'Player1' not in game:
                game['HashedBoard1'] = self._board
                size = len(self._board)
                game['TargetBoard1'] = [['?'] * size for _ in range(size)]
                game['Player1'] = self.OriginatorID
            else:
                game['HashedBoard2'] = self._board
                size = len(self._board)
                game['TargetBoard2'] = [['?'] * size for _ in range(size)]
                game['Player2'] = self.OriginatorID

                # Move to 'P1-NEXT' as both boards have been entered.
                game["State"] = 'P1-NEXT'

            store[self._name] = game
        elif self._action == 'FIRE':
            game = store[self._name].copy()

            # Reveal the previously targeted space
            if 'LastFireColumn' in game:
                if game['State'] == 'P1-NEXT':
                    target_board = 'TargetBoard2'
                else:
                    target_board = 'TargetBoard1'

                col = ord(game['LastFireColumn']) - ord('A')
                row = int(game['LastFireRow']) - 1
                if self._reveal_space != '-':
                    game[target_board][row][col] = 'H'
                else:
                    game[target_board][row][col] = 'M'

                # calculate number of hits for later determination
                # of win
                number_of_hits = sum(
                    sum([1 if space == 'H' else 0 for space in row])
                    for row in game[target_board])
            else:
                number_of_hits = None

            # Update LastFireColumn and LastFireRow in the store so
            # they can be used in the next transaction.
            game['LastFireColumn'] = self._column
            game['LastFireRow'] = self._row

            # if the game has been won, change the State
            # to P1-WIN or P2-WIN as appropriate
            total_ship_spaces = sum([len(ship) for ship in game['Ships']])
            if number_of_hits is not None and \
                    total_ship_spaces == number_of_hits:
                if target_board == 'TargetBoard2':
                    game['State'] = 'P2-WIN'
                else:
                    game['State'] = 'P1-WIN'

            if game['State'] == 'P1-NEXT':
                game['State'] = 'P2-NEXT'
            elif game['State'] == 'P2-NEXT':
                game['State'] = 'P1-NEXT'

            store[self._name] = game
        else:
            raise InvalidTransactionError("invalid state: {}".format(
                store[self._name].copy))
Exemplo n.º 9
0
    def postmsg(self, msgtype, info, path=''):
        """
        Post a transaction message to the validator, parse the returning CBOR
        and return the corresponding dictionary.
        """

        logger.debug(dict2json(info))

        data = dict2cbor(info)
        datalen = len(data)
        url = self.BaseURL + path + msgtype

        logger.debug(
            'post transaction to %s with DATALEN=%d, '
            'base64(DATA)=<%s>', url, datalen, base64.b64encode(data))

        try:
            request = urllib2.Request(url, data, {
                'Content-Type': 'application/cbor',
                'Content-Length': datalen
            })
            opener = urllib2.build_opener(self.ProxyHandler)

            if path == '/prevalidation':
                if self._cookie:
                    request.add_header('cookie', self._cookie)
                response = opener.open(request, timeout=10)
                if not self._cookie:
                    self._cookie = response.headers.get('Set-Cookie')
                    logger.debug('self._cookie %s', self._cookie)
            else:
                response = opener.open(request, timeout=10)

        except urllib2.HTTPError as err:
            logger.warn('operation failed with response: %s', err.code)
            self._print_error_information_from_server(err)
            if err.code == 400:
                err_content = err.read()
                if err_content.find("InvalidTransactionError"):
                    raise InvalidTransactionError(
                        "Error from server: {0}".format(err_content))

            raise MessageException(
                'operation failed with response: {0}'.format(err.code))

        except urllib2.URLError as err:
            logger.warn('operation failed: %s', err.reason)
            raise MessageException('operation failed: {0}'.format(err.reason))

        except:
            logger.warn('no response from server')
            raise MessageException('no response from server')

        content = response.read()
        headers = response.info()
        response.close()

        encoding = headers.get('Content-Type')

        if encoding == 'application/json':
            value = json2dict(content)
        elif encoding == 'application/cbor':
            value = cbor2dict(content)
        else:
            logger.info('server responds with message %s of type %s', content,
                        encoding)
            return None

        logger.debug(pretty_print_dict(value))
        return value
Exemplo n.º 10
0
    def check_valid(self, store, txn):
        if txn.Identifier in store:
            raise InvalidTransactionError("ObjectId already in store")

        if not market_place_object_update.global_is_valid_name(
                store, self._name, self.ObjectType, self._creator_id):
            raise InvalidTransactionError("Name isn't valid")

        if not market_place_object_update.global_is_permitted(
                store, txn, self._creator_id, self.CreatorType):
            logger.debug('failed permission check on offer %s', txn.Identifier)
            raise InvalidTransactionError(
                "Creator address not the same as txn.OriginatorID")

        if not liability_update.LiabilityObject.is_valid_object(
                store, self._input_id):
            logger.debug('input liability %s is not valid in offer %s ',
                         self._input_id, txn.Identifier)
            raise InvalidTransactionError(
                "InputId, {}, is not a liability".format(str(self._input_id)))

        obj = liability_update.LiabilityObject.get_valid_object(
            store, self._input_id)
        if not self.CreatorType.is_valid_creator(store, obj.get('creator'),
                                                 txn.OriginatorID):
            logger.info('%s does not have permission to modify liability %s',
                        txn.OriginatorID, self._input_id)
            raise InvalidTransactionError(
                "txn.OriginatorID is not liability creator")

        if not liability_update.LiabilityObject.is_valid_object(
                store, self._output_id):
            logger.debug('output liability %s is not valid in offer %s ',
                         self._output_id, txn.Identifier)
            raise InvalidTransactionError("OutputID is not a valid liability")

        obj = liability_update.LiabilityObject.get_valid_object(
            store, self._output_id)
        if not self.CreatorType.is_valid_creator(store, obj.get('creator'),
                                                 txn.OriginatorID):
            logger.info('%s does not have permission to modify liability %s',
                        txn.OriginatorID, self._output_id)
            raise InvalidTransactionError(
                "Output Liability creator is not the same as "
                "txn.OriginatorID")

        if self._ratio <= 0:
            logger.debug('invalid ratio %s in offer %s', self._ratio,
                         txn.Identifier)
            raise InvalidTransactionError("Ratio is less than or equal to 0")

        if self._minimum < 0 or self._maximum < 0 or \
                self._maximum < self._minimum:
            logger.debug('inconsistent range %s < %s in offer %s',
                         self._minimum, self._maximum, txn.Identifier)
            raise InvalidTransactionError(
                "Minimum and Maximum are inconsistent")

        if self._execution not in ExchangeOfferObject.ExecutionStyle:
            logger.debug('invalid execution style %s in offer %s',
                         self._execution, txn.Identifier)
            raise InvalidTransactionError(
                "Execution not a valid ExecutionStyle")
Exemplo n.º 11
0
    def check_valid(self, store, txn):
        try:
            store.lookup('participant:key-id', txn.OriginatorID)
        except KeyError:
            raise InvalidTransactionError("Creator was not found : {}".format(
                txn.OriginatorID))

        if self._object_id in store:
            raise InvalidTransactionError(
                "Object with id already exists: {}".format(self._object_id))

        try:
            store.lookup('organization:ticker', self._issuer)
        except KeyError:
            raise InvalidTransactionError("No such ticker: {}".format(
                self._issuer))

        if self._isin is None and self._cusip is None:
            raise InvalidTransactionError("A bond needs either Isin or Cusip")

        try:
            store.lookup("bond:isin", self._isin)
            raise InvalidTransactionError(
                "Object with isin already exists: {}".format(self._isin))
        except KeyError:
            pass

        try:
            store.lookup("bond:cusip", self._cusip)
            raise InvalidTransactionError(
                "Object with cusip already exists: {}".format(self._cusip))
        except KeyError:
            pass

        if self._coupon_type != "Floating" and self._coupon_type != "Fixed":
            raise InvalidTransactionError("Coupon type must be Floating "
                                          "or Fixed: {}".format(self._cusip))

        # keys mentioned in libor
        libor = [
            'Overnight', 'OneWeek', 'OneMonth', 'TwoMonth', 'ThreeMonth',
            'SixMonth', 'OneYear'
        ]

        if self._coupon_benchmark is not None and  \
                self._coupon_benchmark not in libor:
            raise InvalidTransactionError("Coupon Benchmark must a Libor"
                                          " benchmark:"
                                          "{}".format(self._coupon_benchmark))

        if self._coupon_type == "Floating" and self._coupon_benchmark is None:
            raise InvalidTransactionError("Coupon Benchmark must be Libor:"
                                          " {}".format(self._coupon_benchmark))

        try:
            datetime.datetime.strptime(self._maturity_date, "%m/%d/%Y")
        except ValueError:
            raise InvalidTransactionError("Maturity Date is in the wrong "
                                          "format: "
                                          "{}".format(self._maturity_date))

        frequencies = ['Quarterly', 'Monthly', 'Daily']

        if (self._coupon_frequency is not None
                and self._coupon_frequency not in frequencies):
            raise InvalidTransactionError("Coupon Frequency must be "
                                          "one of: {}".format(frequencies))

        try:
            datetime.datetime.strptime(self._first_coupon_date, "%m/%d/%Y")
        except ValueError:
            raise InvalidTransactionError("First Coupon Date is in the wrong "
                                          "format: "
                                          "{}".format(self._first_coupon_date))
Exemplo n.º 12
0
    def check_valid(self, store, txn):
        if self._object_id in store:
            raise InvalidTransactionError(
                "Object with id already exists: {}".format(self._object_id))
        try:
            firm = store.lookup('organization:pricing-source', self._firm)
        except KeyError:
            raise InvalidTransactionError("No such pricing source: {}".format(
                self._firm))

        if self._isin is None and self._cusip is None:
            raise InvalidTransactionError(
                "Cusip or Isin must be set: {}".format(self._object_id))

        if self._isin is not None and self._cusip is None:
            try:
                store.lookup('bond:isin', self._isin)
            except KeyError:
                raise InvalidTransactionError("No such Bond: {}".format(
                    self._firm))

        if self._isin is None and self._cusip is not None:
            try:
                store.lookup('bond:cusip', self._cusip)
            except KeyError:
                raise InvalidTransactionError("No such Bond: {}".format(
                    self._cusip))

        if self._isin is not None and self._cusip is not None:
            try:
                cusip_id = store.lookup('bond:cusip', self._cusip)["object-id"]
                isin_id = store.lookup('bond:isin', self._isin)["object-id"]
            except KeyError:
                raise InvalidTransactionError("No such Bond: {}, {}".format(
                    self._cusip, self._isin))

            if cusip_id != isin_id:
                raise InvalidTransactionError("Cusip {} and Isin {} do not "
                                              "belong to the same bond".format(
                                                  cusip_id, isin_id))

        try:
            submitter = store.lookup("participant:key-id", txn.OriginatorID)
        except KeyError:
            raise InvalidTransactionError("Only an authorized marketmaker can"
                                          " create a quote")

        if "authorization" not in firm:
            raise InvalidTransactionError("Only an authorized marketmaker can"
                                          " create a quote")

        participant = {
            "participant-id": submitter["object-id"],
            "role": "marketmaker"
        }
        if participant not in firm["authorization"]:
            raise InvalidTransactionError("Only an authorized marketmaker can"
                                          " create a quote")

        try:
            bond_utils.bondprice_to_float(self._bid_price)
        except Exception:
            raise InvalidTransactionError("Bid price is not formatted "
                                          "correctly for "
                                          "quote {}".format(self._object_id))

        try:
            bond_utils.bondprice_to_float(self._ask_price)
        except Exception:
            raise InvalidTransactionError("Ask price is not formatted "
                                          "correctly for "
                                          "quote {}".format(self._object_id))
Exemplo n.º 13
0
    def check_valid(self, store, txn):
        if self._object_id not in store:
            raise InvalidTransactionError(
                "Order with object-id doesn't exist: {}".format(
                    self._object_id))
        try:
            order_obj = store.get(self._object_id, 'order')
        except KeyError:
            raise InvalidTransactionError(
                "Object id doesn't refer to an order.")

        if self._quote_id is not None:
            if self._quote_id not in store:
                raise InvalidTransactionError(
                    "No quote with quote id: {}".format(self._quote_id))
            try:
                quote_obj = store.get(self._quote_id, 'quote')
            except KeyError:
                raise InvalidTransactionError(
                    "Quote id does not reference a quote")

            if quote_obj['status'] != 'Open':
                raise InvalidTransactionError(
                    "Referenced quote id: {} on order update for order: {} "
                    "has been closed".format(self._quote_id, self._object_id))

            try:
                if 'cusip' in quote_obj:
                    quote_bond = store.lookup('bond:cusip', quote_obj['cusip'])
                elif 'isin' in quote_obj:
                    quote_bond = store.lookup('bond:isin', quote_obj['isin'])

                if 'cusip' in order_obj:
                    order_bond = store.lookup('bond:cusip', order_obj['cusip'])
                elif 'isin' in order_obj:
                    order_bond = store.lookup('bond:isin', order_obj['isin'])
            except KeyError:
                raise InvalidTransactionError(
                    "Referenced order or quote bond does not appear "
                    "in store.")

            if quote_bond is None or order_bond is None:
                raise InvalidTransactionError(
                    "Could not lookup bond for both quote: {} and "
                    "order: {}".format(self._quote_id, self._object_id))

            if quote_bond['object-id'] != order_bond['object-id']:
                raise InvalidTransactionError(
                    "Referenced quote id: {} on order update for order: {} "
                    "does not match the bond on "
                    "the order".format(self._quote_id, self._object_id))

            if order_obj['action'] == 'Buy':
                if quote_obj['ask-qty'] < order_obj['quantity']:
                    raise InvalidTransactionError(
                        "Quote id: {} does not have sufficient quantity to "
                        "satisfy order: {}".format(self._quote_id,
                                                   self._object_id))
            elif order_obj['action'] == 'Sell':
                if quote_obj['bid-qty'] < order_obj['quantity']:
                    raise InvalidTransactionError(
                        "Quote id: {} does not have sufficient quantity to "
                        "satisfy order: {}".format(self._quote_id,
                                                   self._object_id))

        if (self._status is not None
                and self._status not in ['Open', 'Matched', 'Settled']):
            raise InvalidTransactionError(
                "Status must be either Open, Matched, or Settled.")
Exemplo n.º 14
0
    def check_valid(self, store, txn):
        if self._object_id in store:
            raise InvalidTransactionError(
                "Object with id already exists: {}".format(self._object_id))

        if self._action not in ['Buy', 'Sell']:
            raise InvalidTransactionError("Action must be either Buy or Sell")

        for att in [
                self._action, self._object_id, self._order_type, self._firm_id,
                self._quantity
        ]:
            if att is None:
                raise InvalidTransactionError("Action, ObjectId, "
                                              "OrderType, FirmId, and "
                                              "Quantity are "
                                              "required.")
        if self._firm_id not in store:
            raise InvalidTransactionError("No organization with FirmId")

        try:
            store.get(self._firm_id, 'organization')
        except KeyError:
            raise InvalidTransactionError(
                "FirmId does not reference an organization")
        try:
            _ = store.lookup("participant:key-id", txn.OriginatorID)
        except KeyError:
            raise InvalidTransactionError("Only participants can create an "
                                          "order")

        if self._order_type == 'Limit':
            if self._limit_yield is None and self._limit_price is None:
                raise InvalidTransactionError("For Limit orders,"
                                              "either limit yield or "
                                              "limit price "
                                              "must be specified.")
        elif self._order_type == 'Market':
            if self._limit_price is not None or self._limit_yield is not None:
                raise InvalidTransactionError("Cannot set a market order with "
                                              "limit yield or limit price")
        else:
            raise InvalidTransactionError("OrderType must either be Market "
                                          "or Limit.")

        if self._limit_price is not None:
            try:
                bond_utils.bondprice_to_float(self._limit_price)
            except Exception:
                raise InvalidTransactionError("Limit price is not formatted "
                                              "correctly for order "
                                              "{}".format(self._object_id))

        if self._isin is not None:
            if self._cusip is not None:
                try:
                    bond_by_isin = store.lookup('bond:isin', self._isin)
                    bond_by_cusip = store.lookup('bond:cusip', self._cusip)
                    if bond_by_isin != bond_by_cusip:
                        raise InvalidTransactionError("Isin and Cusip "
                                                      "reference "
                                                      "different bonds.")
                    self.__bond__ = bond_by_isin
                except KeyError:
                    raise InvalidTransactionError("Missing bond with isin or "
                                                  "cusip")
            else:
                try:
                    self.__bond__ = store.lookup('bond:isin', self._isin)
                except KeyError:
                    raise InvalidTransactionError("Bond with that isin "
                                                  "doesn't exist.")
        else:
            if self._cusip is not None:
                try:
                    self.__bond__ = store.lookup('bond:cusip', self._cusip)
                except KeyError:
                    raise InvalidTransactionError("Bond with that cusip "
                                                  "doesn't exist.")
            else:
                raise InvalidTransactionError("At least one of isin or cusip "
                                              "is needed.")
        try:
            self.__organization__ = store.get(self._firm_id, 'organization')
        except KeyError:
            raise InvalidTransactionError("FirmId does not reference an "
                                          "organization.")
Exemplo n.º 15
0
    def render_post(self, request, components, msg):
        """
        Do server-side session prevalidation.
        """
        session = request.getSession()
        if not session:
            raise \
                Error(http.BAD_REQUEST, 'Session has not been started')

        data = request.content.getvalue()
        msg = self._get_message(request)
        mymsg = copy.deepcopy(msg)

        if hasattr(mymsg, 'Transaction') and mymsg.Transaction is not None:
            mytxn = mymsg.Transaction
            LOGGER.info(
                'starting server-side prevalidation '
                'for txn id: %s type: %s', mytxn.Identifier,
                mytxn.TransactionTypeName)

            transaction_type = mytxn.TransactionTypeName

            temp_store_session = ITempTransactionTypeStore(session)
            temp_store_session.count += 1
            LOGGER.debug('visit %d times in the session.uid: %s',
                         temp_store_session.count, session.uid)

            if not temp_store_session.my_store:
                temp_store_map = self._get_store_map()
                if transaction_type not in temp_store_map.transaction_store:
                    LOGGER.info('transaction type %s not in global store map',
                                transaction_type)
                    raise Error(
                        http.BAD_REQUEST, 'unable to prevalidate enclosed '
                        'transaction {0}'.format(data))

                tstore = temp_store_map.get_transaction_store(transaction_type)
                temp_store_session.my_store = tstore.clone_store()

            try:
                if not mytxn.is_valid(temp_store_session.my_store):
                    raise InvalidTransactionError('invalid transaction')

            except InvalidTransactionError as e:
                LOGGER.info(
                    'submitted transaction fails transaction '
                    'family validation check: %s; %s', request.path,
                    mymsg.dump())
                raise Error(
                    http.BAD_REQUEST,
                    'InvalidTransactionError: failed transaction '
                    'family validation check: {}'.format(str(e)))
            except:
                LOGGER.info('submitted transaction is '
                            'not valid %s; %s; %s', request.path, mymsg.dump(),
                            traceback.format_exc(20))
                raise Error(
                    http.BAD_REQUEST, 'enclosed transaction is not '
                    'valid {}'.format(data))

            LOGGER.info('transaction %s is valid', msg.Transaction.Identifier)
            mytxn.apply(temp_store_session.my_store)

        return msg