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))
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
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')
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']))
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")
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')
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))
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))
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
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")
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))
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))
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.")
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.")
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