def start(self, session): """ Start rotating keys and placing key offers with the XBR market maker. :param session: WAMP session over which to communicate with the XBR market maker. :type session: :class:`autobahn.wamp.protocol.ApplicationSession` """ assert isinstance( session, ApplicationSession ), 'session must be an ApplicationSession, was "{}"'.format(session) assert self._state in [ SimpleSeller.STATE_NONE, SimpleSeller.STATE_STOPPED ], 'seller already running' self._state = SimpleSeller.STATE_STARTING self._session = session self._session_regs = [] self.log.info( 'Start selling from seller delegate address {address} (public key 0x{public_key}..)', address=hl('0x' + self._acct.address), public_key=binascii.b2a_hex(self._pkey.public_key[:10]).decode()) procedure = 'xbr.provider.{}.sell'.format(self._provider_id) reg = yield session.register( self.sell, procedure, options=RegisterOptions(details_arg='details')) self._session_regs.append(reg) self.log.debug('Registered procedure "{procedure}"', procedure=hl(reg.procedure)) for key_series in self._keys.values(): key_series.start() # get the currently active (if any) paying channel for the delegate self._channel = yield session.call( 'xbr.marketmaker.get_active_paying_channel', self._addr) # get the current (off-chain) balance of the paying channel paying_balance = yield session.call( 'xbr.marketmaker.get_paying_channel_balance', self._channel['channel']) self.log.info( 'Delegate has currently active paying channel address {paying_channel_adr}', paying_channel_adr=hl( '0x' + binascii.b2a_hex(self._channel['channel']).decode())) # FIXME self._balance = paying_balance['remaining'] if type(self._balance) == bytes: self._balance = unpack_uint256(self._balance) self._seq = paying_balance['seq'] self._state = SimpleSeller.STATE_STARTED return self._balance
def _create_eip712_data(eth_adr, ed25519_pubkey, key_id, channel_seq, amount, balance): assert type(eth_adr) == bytes and len(eth_adr) == 20 assert type(ed25519_pubkey) == bytes and len(ed25519_pubkey) == 32 assert type(key_id) == bytes and len(key_id) == 16 assert type(channel_seq) == int assert type(amount) == int assert type(balance) == int data = { 'types': { 'EIP712Domain': [ {'name': 'name', 'type': 'string'}, {'name': 'version', 'type': 'string'}, {'name': 'chainId', 'type': 'uint256'}, {'name': 'verifyingContract', 'type': 'address'}, ], 'Transaction': [ # The delegate Ethereum address. {'name': 'adr', 'type': 'address'}, # The delegate Ed25519 public key (32 bytes). {'name': 'pubkey', 'type': 'uint256'}, # The UUID of the data encryption key (16 bytes). {'name': 'key_id', 'type': 'uint128'}, # Channel off-chain transaction sequence number. {'name': 'channel_seq', 'type': 'uint32'}, # Amount of the transaction. {'name': 'amount', 'type': 'uint256'}, # Balance remaining in after the transaction. {'name': 'balance', 'type': 'uint256'}, ], }, 'primaryType': 'Transaction', 'domain': { 'name': 'XBR', 'version': '1', # test chain/network ID 'chainId': 5777, # XBRNetwork contract address 'verifyingContract': XBR_DEBUG_NETWORK_ADDR, }, 'message': { 'adr': eth_adr, 'pubkey': unpack_uint256(ed25519_pubkey), 'key_id': unpack_uint128(key_id), 'channel_seq': channel_seq, 'amount': amount, 'balance': balance, }, } return data
def block_number(self) -> int: """ Primary key: block number. """ if self._block_number is None and self._from_fbs: if self._from_fbs.BlockNumberLength(): _block_number = self._from_fbs.BlockNumberAsBytes() self._block_number = unpack_uint256(bytes(_block_number)) else: self._block_number = 0 return self._block_number
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
def value(self) -> int: """ XBR token transferred. """ if self._value is None and self._from_fbs: if self._from_fbs.TxHashLength(): _value = self._from_fbs.ValueAsBytes() self._value = unpack_uint256(bytes(_value)) else: self._value = 0 return self._value
def closed_at(self) -> int: """ Block number (on the blockchain) when the payment channel was finally closed. """ if self._closed_at is None and self._from_fbs: if self._from_fbs.ClosedAtLength(): _closed_at = self._from_fbs.ClosedAtAsBytes() self._closed_at = unpack_uint256(bytes(_closed_at)) else: self._closed_at = 0 return self._closed_at
def open_at(self) -> int: """ Block number (on the blockchain) when the actor (originally) joined the market. """ if self._open_at is None and self._from_fbs: if self._from_fbs.OpenAtLength(): _open_at = self._from_fbs.OpenAtAsBytes() self._open_at = unpack_uint256(bytes(_open_at)) else: self._open_at = 0 return self._open_at
def registered(self) -> int: """ Block number (on the blockchain) when the member (originally) registered. """ if self._registered is None and self._from_fbs: if self._from_fbs.RegisteredLength(): _registered = self._from_fbs.RegisteredAsBytes() self._registered = unpack_uint256(bytes(_registered)) else: self._registered = 0 return self._registered
def updated(self) -> int: """ The amount of XBR tokens a XBR provider joining the market must deposit. """ if self._updated is None and self._from_fbs: if self._from_fbs.UpdatedLength(): _updated = self._from_fbs.UpdatedAsBytes() self._updated = unpack_uint256(bytes(_updated)) else: self._updated = 0 return self._updated
def joined(self) -> int: """ Block number (on the blockchain) when the actor (originally) joined the market. """ if self._joined is None and self._from_fbs: if self._from_fbs.JoinedLength(): _joined = self._from_fbs.JoinedAsBytes() self._joined = unpack_uint256(bytes(_joined)) else: self._joined = 0 return self._joined
def security(self) -> int: """ Security (XBR tokens) deposited by the actor in the market. """ if self._security is None and self._from_fbs: if self._from_fbs.SecurityLength(): security = self._from_fbs.SecurityAsBytes() self._security = unpack_uint256(bytes(security)) else: self._security = 0 return self._security
def remaining(self) -> int: """ Amount of XBR tokens currently remaining in the payment channel. """ if self._remaining is None and self._from_fbs: if self._from_fbs.RemainingLength(): _remaining = self._from_fbs.RemainingAsBytes() self._remaining = unpack_uint256(bytes(_remaining)) else: self._remaining = 0 return self._remaining
def inflight(self) -> int: """ Amount of XBR tokens reserved to in-flight purchase transactions. """ if self._inflight is None and self._from_fbs: if self._from_fbs.InflightLength(): _inflight = self._from_fbs.InflightAsBytes() self._inflight = unpack_uint256(bytes(_inflight)) else: self._inflight = 0 return self._inflight
def amount(self) -> int: """ Amount of XBR tokens initially deposited into the payment channel. """ if self._amount is None and self._from_fbs: if self._from_fbs.AmountLength(): _amount = self._from_fbs.AmountAsBytes() self._amount = unpack_uint256(bytes(_amount)) else: self._amount = 0 return self._amount
def market_fee(self) -> int: """ The fee taken by the market (beneficiary is the market owner). The fee is a percentage of the revenue of the XBR Provider that receives XBR Token paid for transactions. The fee must be between 0% (inclusive) and 99% (inclusive), and is expressed as a fraction of the total supply of XBR tokens. """ if self._market_fee is None and self._from_fbs: if self._from_fbs.MarketFeeLength(): _market_fee = self._from_fbs.MarketFeeAsBytes() self._market_fee = unpack_uint256(bytes(_market_fee)) else: self._market_fee = 0 return self._market_fee
def published(self) -> int: """ Global market sequence number. """ if self._published is None and self._from_fbs: if self._from_fbs.PublishedLength(): _published = self._from_fbs.PublishedAsBytes() self._published = unpack_uint256(bytes(_published)) else: self._published = 0 return self._published
def paying_channel_after(self) -> int: """ Payment channel balance after transaction. """ if self._paying_channel_after is None and self._from_fbs: if self._from_fbs.PayingChannelAfterLength(): _paying_channel_after = self._from_fbs.PayingChannelAfterAsBytes() self._paying_channel_after = unpack_uint256(bytes(_paying_channel_after)) else: self._paying_channel_after = 0 return self._paying_channel_after
def amount(self) -> int: """ Transaction amount in XBR. """ if self._amount is None and self._from_fbs: if self._from_fbs.AmountLength(): _amount = self._from_fbs.AmountAsBytes() self._amount = unpack_uint256(bytes(_amount)) else: self._amount = 0 return self._amount
def consumer_security(self) -> int: """ The amount of XBR tokens a XBR consumer joining the market must deposit. """ if self._consumer_security is None and self._from_fbs: if self._from_fbs.ConsumerSecurityLength(): _consumer_security = self._from_fbs.ConsumerSecurityAsBytes() self._consumer_security = unpack_uint256( bytes(_consumer_security)) else: self._consumer_security = 0 return self._consumer_security
def parse(data: dict): assert type(data) == dict obj = ChannelBalance() if 'remaining' in data: remaining = data['remaining'] assert type(remaining) == bytes and len(remaining) == 32 obj._remaining = unpack_uint256(remaining) if 'inflight' in data: inflight = data['inflight'] assert type(inflight) == bytes and len(inflight) == 32 obj._inflight = unpack_uint256(inflight) if 'seq' in data: seq = data['seq'] assert type(seq) == int obj._seq = unpack_uint256(seq) return obj
def close_balance(self) -> int: """ Remaining (closing) channel balance (XBR). """ if self._close_balance is None and self._from_fbs: if self._from_fbs.CloseBalanceLength(): _close_balance = self._from_fbs.CloseBalanceAsBytes() if _close_balance is not None: self._close_balance = unpack_uint256(bytes(_close_balance)) else: self._close_balance = 0 else: self._close_balance = 0 return self._close_balance
async def onJoin(self, details): self.log.debug('{klass}.onJoin(details.session={session}, details.authid="{authid}")', klass=self.__class__.__name__, session=details.session, authid=details.authid) self.log.info('-' * 120) self.log.info('Channels in market (off-chain information):') for channel_adr, channel_type, channel_state in self.config.extra.get('channels', []): channel_adr = a2b_hex(channel_adr[2:]) try: # get real-time off-chain channel balance (as maintained within the market maker) if channel_type == 1: channel = await self.call('xbr.marketmaker.get_payment_channel', channel_adr) balance = await self.call('xbr.marketmaker.get_payment_channel_balance', channel_adr) elif channel_type == 2: channel = await self.call('xbr.marketmaker.get_paying_channel', channel_adr) balance = await self.call('xbr.marketmaker.get_paying_channel_balance', channel_adr) except: self.log.failure() else: # initial on-chain channel amount amount = int(unpack_uint256(channel['amount']) / 10 ** 18) remaining = int(unpack_uint256(balance['remaining']) / 10 ** 18) ctype = {0: 'No Channel', 1: 'Payment Channel', 2: 'Paying Channel'}.get(channel['type'], 'UNKNOWN') cstate = {0: None, 1: 'OPEN', 2: 'CLOSING', 3: 'CLOSED', 4: 'FAILED'}.get(channel['state'], 'UNKNOWN') print(' {} 0x{}: market {}, delegate {}, currently in {} state, initial amount {} XBR, current off-chain balance {} XBR'.format(ctype, b2a_hex(channel_adr).decode(), b2a_hex(channel['market']).decode(), b2a_hex(channel['delegate']).decode(), cstate, amount, remaining)) self.log.info('-' * 120) self.leave()
def start(self, session, consumer_id): """ Start buying keys to decrypt XBR data by calling ``unwrap()``. :param session: WAMP session over which to communicate with the XBR market maker. :type session: :class:`autobahn.wamp.protocol.ApplicationSession` :param consumer_id: XBR consumer ID. :type consumer_id: str :return: Current remaining balance in payment channel. :rtype: int """ assert isinstance(session, ApplicationSession) assert type(consumer_id) == str assert not self._running self._session = session self._running = True self.log.info( 'Start buying from consumer delegate address {address} (public key 0x{public_key}..)', address=hl('0x' + self._acct.address), public_key=binascii.b2a_hex(self._pkey.public_key[:10]).decode()) # get the currently active (if any) payment channel for the delegate self._channel = yield session.call( 'xbr.marketmaker.get_active_payment_channel', self._addr) # get the current (off-chain) balance of the payment channel payment_balance = yield session.call( 'xbr.marketmaker.get_payment_channel_balance', self._channel['channel']) self.log.info( 'Delegate has current payment channel address {payment_channel_adr}', payment_channel_adr=hl( '0x' + binascii.b2a_hex(self._channel['channel']).decode())) # FIXME self._balance = payment_balance['remaining'] if type(self._balance) == bytes: self._balance = unpack_uint256(self._balance) self._seq = payment_balance['seq'] return self._balance