def validate_subasset_longname(subasset_longname, subasset_child=None): if subasset_child is None: chunks = subasset_longname.split('.', 1) if (len(chunks) == 2): subasset_child = chunks[1] else: subasset_child = '' if len(subasset_child) < 1: raise exceptions.AssetNameError('subasset name too short') if len(subasset_longname) > 250: raise exceptions.AssetNameError('subasset name too long') # can't start with period, can't have consecutive periods, can't contain anything not in SUBASSET_DIGITS previous_digit = '.' for c in subasset_child: if c not in SUBASSET_DIGITS: raise exceptions.AssetNameError( 'subasset name contains invalid character:', c) if c == '.' and previous_digit == '.': raise exceptions.AssetNameError( 'subasset name contains consecutive periods') previous_digit = c if previous_digit == '.': raise exceptions.AssetNameError('subasset name ends with a period') return True
def generate_asset_id(asset_name, block_index): """Create asset_id from asset_name.""" if asset_name == config.BTC: return 0 elif asset_name == config.XCP: return 1 if len(asset_name) < 4: raise exceptions.AssetNameError('too short') # Numeric asset names. if enabled('numeric_asset_names'): # Protocol change. if asset_name[0] == 'A': # Must be numeric. try: asset_id = int(asset_name[1:]) except ValueError: raise exceptions.AssetNameError( 'non‐numeric asset name starts with ‘A’') # Number must be in range. if not (26**12 + 1 <= asset_id <= 2**64 - 1): raise exceptions.AssetNameError( 'numeric asset name not in range') return asset_id elif len(asset_name) >= 13: raise exceptions.AssetNameError('long asset names must be numeric') if asset_name[0] == 'A': raise exceptions.AssetNameError( 'non‐numeric asset name starts with ‘A’') # Convert the Base 26 string to an integer. n = 0 for c in asset_name: n *= 26 if c not in B26_DIGITS: raise exceptions.AssetNameError('invalid character:', c) digit = B26_DIGITS.index(c) n += digit asset_id = n if asset_id < 26**3: raise exceptions.AssetNameError('too short') return asset_id
def validate_subasset_parent_name(asset_name): if asset_name == config.BTC: raise exceptions.AssetNameError('parent asset cannot be {}'.format(config.BTC)) if asset_name == config.XCP: raise exceptions.AssetNameError('parent asset cannot be {}'.format(config.XCP)) if len(asset_name) < 4: raise exceptions.AssetNameError('parent asset name too short') if len(asset_name) >= 13: raise exceptions.AssetNameError('parent asset name too long') if asset_name[0] == 'A': raise exceptions.AssetNameError('parent asset name starts with ‘A’') for c in asset_name: if c not in B26_DIGITS: raise exceptions.AssetNameError('parent asset name contains invalid character:', c) return True
def unpack(db, message, block_index): try: # account for memo bytes memo_bytes_length = len(message) - LENGTH if memo_bytes_length < 0: raise exceptions.UnpackError('invalid message length') if memo_bytes_length > MAX_MEMO_LENGTH: raise exceptions.UnpackError('memo too long') struct_format = FORMAT + ('{}s'.format(memo_bytes_length)) asset_id, quantity, short_address_bytes, memo_bytes = struct.unpack( struct_format, message) if len(memo_bytes) == 0: memo_bytes = None # unpack address full_address = address.unpack(short_address_bytes) # asset id to name asset = util.generate_asset_name(asset_id, block_index) if asset == config.BTC: raise exceptions.AssetNameError('{} not allowed'.format( config.BTC)) except (struct.error) as e: logger.warning("enhanced send unpack error: {}".format(e)) raise exceptions.UnpackError('could not unpack') except (exceptions.AssetNameError, exceptions.AssetIDError) as e: logger.warning("enhanced send invalid asset id: {}".format(e)) raise exceptions.UnpackError('asset id invalid') unpacked = { 'asset': asset, 'quantity': quantity, 'address': full_address, 'memo': memo_bytes, } return unpacked