Source code for cfxdb.xbrmm.offer

##############################################################################
#
#                        Crossbar.io Database
#     Copyright (c) Crossbar.io Technologies GmbH. Licensed under MIT.
#
##############################################################################

import pprint
import uuid

import flatbuffers
import numpy as np
from cfxdb import pack_uint256, unpack_uint256
from cfxdb.gen.xbrmm import Offer as OfferGen
from zlmdb import table, MapUuidFlatBuffers, MapUuidUuid


class _OfferGen(OfferGen.Offer):
    """
    Expand methods on the class code generated by flatc.

    FIXME: come up with a PR for flatc to generated this stuff automatically.
    """
    @classmethod
    def GetRootAsOffer(cls, buf, offset):
        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
        x = _OfferGen()
        x.Init(buf, n + offset)
        return x

    def OfferAsBytes(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
        if o != 0:
            _off = self._tab.Vector(o)
            _len = self._tab.VectorLen(o)
            return memoryview(self._tab.Bytes)[_off:_off + _len]
        return None

    def SellerAsBytes(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
        if o != 0:
            _off = self._tab.Vector(o)
            _len = self._tab.VectorLen(o)
            return memoryview(self._tab.Bytes)[_off:_off + _len]
        return None

    def KeyAsBytes(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14))
        if o != 0:
            _off = self._tab.Vector(o)
            _len = self._tab.VectorLen(o)
            return memoryview(self._tab.Bytes)[_off:_off + _len]
        return None

    def ApiAsBytes(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16))
        if o != 0:
            _off = self._tab.Vector(o)
            _len = self._tab.VectorLen(o)
            return memoryview(self._tab.Bytes)[_off:_off + _len]
        return None

    def UriAsBytes(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18))
        if o != 0:
            _off = self._tab.Vector(o)
            _len = self._tab.VectorLen(o)
            return memoryview(self._tab.Bytes)[_off:_off + _len]
        return None

    def SignatureAsBytes(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22))
        if o != 0:
            _off = self._tab.Vector(o)
            _len = self._tab.VectorLen(o)
            return memoryview(self._tab.Bytes)[_off:_off + _len]
        return None

    def PriceAsBytes(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(24))
        if o != 0:
            _off = self._tab.Vector(o)
            _len = self._tab.VectorLen(o)
            return memoryview(self._tab.Bytes)[_off:_off + _len]
        return None


[docs]class Offer(object): """ Data encryption key offerings by XBR providers. """ def __init__(self, from_fbs=None): self._from_fbs = from_fbs # uint64 self._timestamp = None # [uint8] (uuid) self._offer = None # [uint8] (address) self._seller = None # uint64 self._seller_session_id = None # string self._seller_authid = None # [uint8] (uuid) self._key = None # [uint8] (uuid) self._api = None # string self._uri = None # uint64 self._valid_from = None # [uint8] self._signature = None # [uint8] (uint256) self._price = None # [KeyValue] self._categories = None # uint64 self._expires = None # uint32 self._copies = None # uint32 self._remaining = None
[docs] def marshal(self) -> dict: obj = { 'timestamp': int(self.timestamp) if self.timestamp else None, 'offer': self.offer.bytes if self.offer else None, 'seller': bytes(self.seller) if self.seller else None, 'seller_session_id': self.seller_session_id, 'seller_authid': self.seller_authid, 'key': self.key.bytes if self.key else None, 'api': self.api.bytes if self.api else None, 'uri': self.uri, 'valid_from': int(self.valid_from) if self.valid_from else None, 'signature': bytes(self.signature) if self.signature else None, 'price': pack_uint256(self.price) if self.price else 0, 'categories': self.categories, 'expires': int(self.expires) if self.expires else None, 'copies': self.copies, 'remaining': self.remaining, } return obj
def __str__(self): return '\n{}\n'.format(pprint.pformat(self.marshal())) @property def timestamp(self) -> np.datetime64: """ Offer transaction time (epoch time in ns) """ if self._timestamp is None and self._from_fbs: self._timestamp = np.datetime64(self._from_fbs.Timestamp(), 'ns') return self._timestamp @timestamp.setter def timestamp(self, value: np.datetime64): assert value is None or isinstance(value, np.datetime64) self._timestamp = value @property def offer(self) -> uuid.UUID: """ ID of the data encryption key offer. """ if self._offer is None and self._from_fbs: if self._from_fbs.OfferLength(): _offer = self._from_fbs.OfferAsBytes() self._offer = uuid.UUID(bytes=bytes(_offer)) return self._offer @offer.setter def offer(self, value: uuid.UUID): assert value is None or isinstance(value, uuid.UUID) self._offer = value @property def seller(self) -> bytes: """ Address of the XBR provider offering the data encryption key. """ if self._seller is None and self._from_fbs: if self._from_fbs.SellerLength(): self._seller = self._from_fbs.SellerAsBytes() return self._seller @seller.setter def seller(self, value: bytes): assert value is None or (type(value) == bytes and len(value) == 20) self._seller = value @property def seller_session_id(self) -> int: """ WAMP session ID of the caller that originally placed this offer. """ if self._seller_session_id is None and self._from_fbs: self._seller_session_id = self._from_fbs.SellerSessionId() return self._seller_session_id @seller_session_id.setter def seller_session_id(self, value: int): assert value is None or type(value) == int self._seller_session_id = value @property def seller_authid(self) -> str: """ WAMP session authid of the caller that originally placed this offer. """ if self._seller_authid is None and self._from_fbs: _seller_authid = self._from_fbs.SellerAuthid() if _seller_authid: self._seller_authid = _seller_authid.decode('utf8') return self._seller_authid @seller_authid.setter def seller_authid(self, value): self._seller_authid = value @property def key(self) -> uuid.UUID: """ ID of the data encryption key offered. """ if self._key is None and self._from_fbs: if self._from_fbs.KeyLength(): _key = self._from_fbs.KeyAsBytes() self._key = uuid.UUID(bytes=bytes(_key)) return self._key @key.setter def key(self, value): assert value is None or isinstance(value, uuid.UUID) self._key = value @property def api(self) -> uuid.UUID: """ ID of the API the encrypted data (this key is for) is provided under. :return: """ if self._api is None and self._from_fbs: if self._from_fbs.ApiLength(): _api = self._from_fbs.ApiAsBytes() self._api = uuid.UUID(bytes=bytes(_api)) return self._api @api.setter def api(self, value: uuid.UUID): assert value is None or isinstance(value, uuid.UUID) self._api = value @property def uri(self) -> str: """ URI under which the data encrypted with the key offered is provided under. """ if self._uri is None and self._from_fbs: _uri = self._from_fbs.Uri() if _uri: self._uri = _uri.decode('utf8') return self._uri @uri.setter def uri(self, value: str): self._uri = value @property def valid_from(self) -> np.datetime64: """ Timestamp from which the offer is valid (epoch time in ns). """ if self._valid_from is None and self._from_fbs: self._valid_from = np.datetime64(self._from_fbs.ValidFrom(), 'ns') return self._valid_from @valid_from.setter def valid_from(self, value: np.datetime64): assert value is None or isinstance(value, np.datetime64) self._valid_from = value @property def signature(self) -> bytes: """ Seller delegate signature for the offer. The signature covers all information of the original offer placement request and requestor. """ if self._signature is None and self._from_fbs: if self._from_fbs.SignatureLength(): self._signature = self._from_fbs.SignatureAsBytes() return self._signature @signature.setter def signature(self, value: bytes): assert value is None or type(value) == bytes self._signature = value @property def price(self) -> int: """ Price of data encryption key in XBR tokens. """ if self._price is None and self._from_fbs: if self._from_fbs.PriceLength(): _price = self._from_fbs.PriceAsBytes() self._price = unpack_uint256(bytes(_price)) else: self._price = 0 return self._price @price.setter def price(self, value: int): assert value is None or type(value) == int self._price = value @property def categories(self) -> dict: """ Dictionary of optional user defined categories the specific data that is provided falls under. """ if self._categories is None and self._from_fbs: num = self._from_fbs.CategoriesKeyLength() if num > 0: categories = {} for i in range(num): key = self._from_fbs.CategoriesKey(i).decode('utf8') value = self._from_fbs.CategoriesValue(i).decode('utf8') categories[key] = value self._categories = categories return self._categories @categories.setter def categories(self, values: dict): assert values is None or type(values) == dict if values: assert (type(key) == str for key in values.keys()) assert (type(value) == str for value in values.values()) self._categories = values @property def expires(self) -> np.datetime64: """ Optional data at which this offer expires (epoch time in ns). """ if self._expires is None and self._from_fbs: self._expires = np.datetime64(self._from_fbs.Expires(), 'ns') return self._expires @expires.setter def expires(self, value: np.datetime64): assert value is None or isinstance(value, np.datetime64) self._expires = value @property def copies(self) -> int: """ Optional maximum number of times this data encryption key is to be sold or 0 for unlimited. """ if self._copies is None and self._from_fbs: self._copies = self._from_fbs.Copies() return self._copies @copies.setter def copies(self, value: int): assert value is None or type(value) == int self._copies = value @property def remaining(self) -> int: """ Remaining number of copies to be sold (if "copies" is set >0, otherwise 0). """ if self._remaining is None and self._from_fbs: self._remaining = self._from_fbs.Remaining() return self._remaining @remaining.setter def remaining(self, value: int): assert value is None or type(value) == int self._remaining = value
[docs] @staticmethod def cast(buf): return Offer(_OfferGen.GetRootAsOffer(buf, 0))
[docs] def build(self, builder): offer = self.offer.bytes if self.offer else None if offer: offer = builder.CreateString(offer) seller = self.seller if seller: seller = builder.CreateString(seller) seller_authid = self.seller_authid if seller_authid: seller_authid = builder.CreateString(seller_authid) key = self.key.bytes if self.key else None if key: key = builder.CreateString(key) api = self.api.bytes if self.api else None if api: api = builder.CreateString(api) uri = self.uri if uri: uri = builder.CreateString(uri) signature = self.signature if signature: signature = builder.CreateString(signature) price = self.price if price: price = builder.CreateString(pack_uint256(price)) categories_keys_vec = None categories_values_vec = None if self._categories: categories_keys = [] categories_values = [] for _key, _value in sorted(self._categories.items()): assert type(_key) == str, 'category key must be string, but was {}: {}'.format( type(_key), _key) assert type(_value) == str, 'category value must be string, but was {}: {}'.format( type(_value), _value) categories_keys.append(builder.CreateString(_key)) categories_values.append(builder.CreateString(_value)) OfferGen.OfferStartCategoriesKeyVector(builder, len(categories_keys)) for _key in categories_keys: builder.PrependUOffsetTRelative(_key) categories_keys_vec = builder.EndVector() OfferGen.OfferStartCategoriesValueVector(builder, len(categories_values)) for _value in categories_values: builder.PrependUOffsetTRelative(_value) categories_values_vec = builder.EndVector() OfferGen.OfferStart(builder) if self.timestamp: OfferGen.OfferAddTimestamp(builder, int(self.timestamp)) if offer: OfferGen.OfferAddOffer(builder, offer) if seller: OfferGen.OfferAddSeller(builder, seller) if self.seller_session_id: OfferGen.OfferAddSellerSessionId(builder, self.seller_session_id) if seller_authid: OfferGen.OfferAddSellerAuthid(builder, seller_authid) if key: OfferGen.OfferAddKey(builder, key) if api: OfferGen.OfferAddApi(builder, api) if uri: OfferGen.OfferAddUri(builder, uri) if self.valid_from: OfferGen.OfferAddValidFrom(builder, int(self.valid_from)) if signature: OfferGen.OfferAddSignature(builder, signature) if price: OfferGen.OfferAddPrice(builder, price) if categories_keys_vec: OfferGen.OfferAddCategoriesKey(builder, categories_keys_vec) if categories_values_vec: OfferGen.OfferAddCategoriesValue(builder, categories_values_vec) if self.expires: OfferGen.OfferAddExpires(builder, int(self.expires)) if self.copies: OfferGen.OfferAddCopies(builder, self.copies) if self.remaining: OfferGen.OfferAddRemaining(builder, self.remaining) final = OfferGen.OfferEnd(builder) return final
[docs]@table('dc6d175b-3dd0-4b1f-a6e8-2aec7f0e3fe5', build=Offer.build, cast=Offer.cast) class Offers(MapUuidFlatBuffers): """ Persisted data encryption key offers. Map :class:`zlmdb.MapBytes32FlatBuffers` from ``offer_id`` to :class:`cfxdb.xbr.Offer` """
[docs]@table('ef5f1cdc-4871-4a03-ac1c-c60e80875b8b') class IndexOfferByKey(MapUuidUuid): """ Index: key_id -> offer_id """