o
    @Bihz                     @   s   d dl Z d dlZd dlZd dlZd dlmZmZ d dlmZm	Z	 d dl
mZ ddlmZmZ d dlmZ d dlZd dlZd dlZd dlZd dlZd dlZddlmZmZmZ G d	d
 d
eZG dd deZG dd deZdS )    N)RegisterOptionsCallDetails)ApplicationErrorTransportLost)ApplicationSession   )unpack_uint256pack_uint256)time_ns)hlrecover_eip712_signersign_eip712_datac                   @   sN   e Zd ZdZdddZedd Zdd Zd	d
 Zdd Z	dd Z
dd ZdS )	KeySeriesz}
    Data encryption key series with automatic (time-based) key rotation
    and key offering (to the XBR market maker).
    Nc                 C   s   t |tkrt|dksJ t |tkr|dksJ t |tkr$|dks&J |du s0t|s0J || _|| _|| _|| _d| _	d| _
d| _i | _dS )a}  

        :param api_id: ID of the API for which to generate keys.
        :type api_id: bytes

        :param price: Price per key in key series.
        :type price: int

        :param interval: Key rotation interval in seconds.
        :type interval: int

        :param on_rotate: Optional user callback fired after key was rotated.
        :type on_rotate: callable
           r   N)typebyteslenintcallable_api_id_price	_interval
_on_rotate_id_key_box_archive)selfapi_idpriceinterval	on_rotate r"   T/var/www/html/Trade-python/venv/lib/python3.10/site-packages/autobahn/xbr/_seller.py__init__8   s   
zKeySeries.__init__c                 C   s   | j S )z
        Get current XBR data encryption key ID (of the keys being rotated
        in a series).

        :return: Current key ID in key series (16 bytes).
        :rtype: bytes
        )r   r   r"   r"   r#   key_idV   s   	zKeySeries.key_idc                 C   s"   t |}| j|}| jd|fS )z
        Encrypt data with the current XBR data encryption key.

        :param payload: Application payload to encrypt.
        :type payload: object

        :return: The ciphertext for the encrypted application payload.
        :rtype: bytes
        cbor)cbor2dumpsr   encryptr   )r   payloaddata
ciphertextr"   r"   r#   r*   a   s   

zKeySeries.encryptc                 C   sx   t |tkrt|dksJ t |tkrt|dksJ | j| \}}tjtjj|tjj	d}|j
|tjj	d}|S )a  
        Encrypt a (previously used) XBR data encryption key with a buyer public key.

        :param key_id: ID of the data encryption key to encrypt.
        :type key_id: bytes

        :param buyer_pubkey: Buyer WAMP public key (Ed25519) to asymmetrically encrypt
            the data encryption key (selected by ``key_id``) against.
        :type buyer_pubkey: bytes

        :return: The ciphertext for the encrypted data encryption key.
        :rtype: bytes
        r       )encoder)r   r   r   r   naclpublic	SealedBox	PublicKeyencoding
RawEncoderr*   )r   r&   buyer_pubkeykey_sendkey_boxencrypted_keyr"   r"   r#   encrypt_keyp   s   zKeySeries.encrypt_keyc                 C      t  NNotImplementedErrorr%   r"   r"   r#   start      zKeySeries.startc                 C   r<   r=   r>   r%   r"   r"   r#   stop   rA   zKeySeries.stopc                    s   t d| _tjtjjj| _	tj| j	| _
| j	| j
f| j| j< | jjdtdddttj| jdttj| jdd | jrL| | I d H  d S d S )Nr   z4{tx_type} key "{key_id}" rotated [api_id="{api_id}"]z
XBR ROTATEmagentacolorr   )tx_typer&   r   )osurandomr   r0   utilsrandomsecret	SecretBoxKEY_SIZEr   r   r   loginfor   uuidUUIDr   r   r%   r"   r"   r#   _rotate   s   
zKeySeries._rotater=   )__name__
__module____qualname____doc__r$   propertyr&   r*   r;   r@   rB   rS   r"   r"   r"   r#   r   2   s    


r   c                   @   s   e Zd Zdd ZdS )PayingChannelc                 C   sb   t |tkrt|dksJ t |tkr|dksJ t |tkr$|dks&J || _|| _|| _d S )N   r   )r   r   r   r   _adr_seq_balance)r   adrseqbalancer"   r"   r#   r$      s   
zPayingChannel.__init__N)rT   rU   rV   r$   r"   r"   r"   r#   rY      s    rY   c                   @   s~   e Zd ZdZdZdZdZdZdZdZ	dddZ
ed	d
 ZdddZdd Zdd Zdd Zdd Z	dddZdddZdS )SimpleSellerNr   r            c                 C   s   t |tkrt|dksJ d|t |tkrt|dks&J d||du s7t |tks7J d|t | _tj	| _
|| _|| _tj|| _d| _| jj | _d| _|pat| jj| _i | _d| _d| _d| _i | _i | _d| _d| _dS )a  

        :param market_maker_adr: Market maker public Ethereum address (20 bytes).
        :type market_maker_adr: bytes

        :param seller_key: Seller (delegate) private Ethereum key (32 bytes).
        :type seller_key: bytes

        :param provider_id: Optional explicit data provider ID. When not given, the seller delegate
            public WAMP key (Ed25519 in Hex) is used as the provider ID. This must be a valid WAMP URI part.
        :type provider_id: string
        rZ   z0market_maker_adr must be bytes[20], but got "{}"r.   z/seller delegate must be bytes[32], but got "{}"Nz0provider_id must be None or string, but got "{}"r   )r   r   r   formatstrtxaiomake_loggerrO   ra   
STATE_NONE_state_market_maker_adr	_pkey_raweth_keyskeys
PrivateKey_pkey_acct
public_keyto_canonical_address_addr_caddr_provider_id	_channels_channelr]   r\   _keys	_keys_map_session_session_regs)r   market_maker_adr
seller_keyprovider_idr"   r"   r#   r$      s(   &&"

zSimpleSeller.__init__c                 C   s   | j jS )z
        This seller delegate public Ethereum key.

        :return: Ethereum public key of this seller delegate.
        :rtype: bytes
        )rp   rr   r%   r"   r"   r#   rr      s   zSimpleSeller.public_keyc                    s   t  tkrt dkr jvsJ t tkrdksJ t |tkr)|dks+J du sKt tkrGdd  D rGdd  D sKJ d fdd	} ||}|j < j	j
d
|d |S )a  
        Add a new (rotating) private encryption key for encrypting data on the given API.

        :param api_id: API for which to create a new series of rotating encryption keys.
        :type api_id: bytes

        :param price: Price in XBR token per key.
        :type price: int

        :param interval: Interval (in seconds) in which to auto-rotate the encryption key.
        :type interval: int
        r   r   Nc                 s       | ]	}t |tkV  qd S r=   r   rf   ).0kr"   r"   r#   	<genexpr>      z#SimpleSeller.add.<locals>.<genexpr>c                 s   r   r=   r   )r   vr"   r"   r#   r     r   zZinvalid categories type (must be dict) or category key or value type (must both be string)c           	         s  | j }| j|< d}|rzqt d }j}td}j}jjd| |||d d ur1t	nd d d |dI d H }j
jdtddd	ttj|d
ttj d
ttd ur_td ndd dd	tt| td j
jd|d W d S  ty } z|jdkrj
d nj
  W Y d }~d S W Y d }~nd }~w ty   j
d Y d S    j
  Y |d8 }j
jd|d tdI d H  |sd S d S )N   l    d(	 A   zxbr.marketmaker.place_offer)privkeyr   
categoriesexpirescopiesr   zh{tx_type} key "{key_id}" offered for {price} [api_id={api_id}, prefix="{prefix}", delegate="{delegate}"]z
XBR OFFER rC   rD   rF        NZor    XBR)rG   r&   r   r   delegateprefixzoffer={offer})offerzwamp.error.no_such_procedurez-xbr.marketmaker.offer: procedure unavailable!z2TransportLost while calling xbr.marketmaker.offer!r   z6Failed to place offer for key! Retrying {retries}/5 ..)retries)r&   rz   r
   rt   rH   rI   rv   r{   callr	   rO   rP   r   rQ   rR   rf   r   binasciib2a_hexdecodedebugr   errorwarnfailurer   asynciosleep)	
key_seriesr&   r   
valid_fromr   	signaturer   r   er   r   r   r   r   r"   r#   r!     sf   



&	

z#SimpleSeller.add.<locals>.on_rotatez#Created new key series {key_series})r   )r   r   r   ry   r   dictrn   valuesr   rO   rP   )r   r   r   r   r    r   r!   r   r"   r   r#   add  s   &@=
zSimpleSeller.addc                    s  t |tsJ d|| jtjtjfv sJ dtj| _|| _g | _	| j
jdt| jt| jjdd  d d| j}|j| j|tdd	d
I dH }| j	| | j
jdt|jd d| j}|j| j|tdd	d
I dH }| j	| | j
jdt|jd | j D ]	}| I dH  q|d| jI dH }|d|d I dH }t |d t!krt"|d |d< | j
jdtdt|d   d t#|d |d |d | j$|d < tj%| _|| _&|d | _'t | j't!krt"| j'| _'|d | _(|d S )z
        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`
        z/session must be an ApplicationSession, was "{}"zseller already runningzRStart selling from seller delegate address {address} (public key 0x{public_key}..)N
   )addressrr   zxbr.provider.{}.selldetails)details_arg)optionsz"Registered procedure "{procedure}")	procedurezxbr.provider.{}.close_channelz)xbr.marketmaker.get_active_paying_channelz*xbr.marketmaker.get_paying_channel_balancechannel	remainingzIDelegate has currently active paying channel address {paying_channel_adr}0x)paying_channel_adrr_   ))
isinstancer   re   rj   ra   ri   STATE_STOPPEDSTATE_STARTINGr{   r|   rO   rP   r   ru   r   r   rp   rr   r   rv   registersellr   appendr   r   close_channelry   r   r@   r   rt   r   r   r   rY   rw   STATE_STARTEDrx   r]   r\   )r   sessionr   regr   r   paying_balancer"   r"   r#   r@   ]  sF   "

zSimpleSeller.startc                    s   | j tjfv sJ dtj| _ g }| j D ]}| }|| q| jr@| j	r=| j	
 r=| jD ]}| }|| q1d| _t|}z%z|I dH  W n   | j  Y W tj| _ d| _	dS W tj| _ d| _	dS tj| _ d| _	w )zF
        Stop rotating/offering keys to the XBR market maker.
        seller not runningN)rj   ra   r   STATE_STOPPINGry   r   rB   r   r|   r{   is_attached
unregisterrg   gatherrO   r   r   )r   dlr   dr   r"   r"   r#   rB     s2   



zSimpleSeller.stopc                    sN   | j tjfvrtd| jr| j std| jd| jd I dH }|S )a  
        Return current (off-chain) balance of paying channel:

        * ``amount``: The initial amount with which the paying channel was opened.
        * ``remaining``: The remaining amount of XBR in the paying channel that can be earned.
        * ``inflight``: The amount of XBR allocated to sell transactions that are currently processed.

        :return: Current paying balance.
        :rtype: dict
        r   z!market-maker session not attachedz+xbr.marketmaker.get_payment_channel_balancer   N)rj   ra   r   RuntimeErrorr{   r   r   rx   )r   r   r"   r"   r#   r`     s   zSimpleSeller.balancec                    sh   t |tkrt|dkr|| jv sJ t |tksJ |dus"J | j| }||\}}}|||fS )aG  
        Encrypt and wrap application payload for a given API and destined for a specific WAMP URI.

        :param api_id: API for which to encrypt and wrap the application payload for.
        :type api_id: bytes

        :param uri: WAMP URI the application payload is destined for (eg the procedure or topic URI).
        :type uri: str

        :param payload: Application payload to encrypt and wrap.
        :type payload: object

        :return: The encrypted and wrapped application payload: a tuple with ``(key_id, serializer, ciphertext)``.
        :rtype: tuple
        r   N)r   r   r   ry   rf   r*   )r   r   urir+   	keyseriesr&   
serializerr-   r"   r"   r#   wrap  s   &

zSimpleSeller.wrapc              
   C   s  t |tkrt|dksJ dt |t |tkr!t|dks*J dt |t |tks9J dt |t |tkrEt|dksNJ dt |t |tks]J dt |t |tkrit|dksrJ d	t ||d
u st|tsJ d|| jkrt	dd| j
jt| j t| || jd kr| j  t	dd| j
jt| jd  t| || jkrt	dd| j
j| jd |t|}|| jkrt	dd| j
j| j|t|||||}||kr| jjd| j
jtt| tt| d t	dd| j
jt| j||||}	| j|t|||	d}
| jjd| j
jtdddttt|d d  ddt|tt| t|jt|j d! |
S )"zI
        Called by a XBR Market Maker to close a paying channel.
        rZ   z.market_maker_adr must be bytes[20], but was {}z)channel_adr must be bytes[20], but was {}z#channel_seq must be int, but was {}r.   z-channel_balance must be bytes[32], but was {}z)channel_is_final must be bool, but was {}r   z3marketmaker_signature must be bytes[65], but was {}N/details must be autobahn.wamp.types.CallDetailsz!xbr.error.unexpected_delegate_adrzS{}.sell() - unexpected market maker (delegate) address: expected 0x{}, but got 0x{}r    xbr.error.unexpected_channel_adrJ{}.sell() - unexpected paying channel address: expected 0x{}, but got 0x{} xbr.error.unexpected_channel_seqR{}.sell() - unexpected channel (after tx) sequence number: expected {}, but got {}r   $xbr.error.unexpected_channel_balanceJ{}.sell() - unexpected channel (after tx) balance: expected {}, but got {}t{klass}.sell()::XBRSIG[4/8] - EIP712 signature invalid: signer_address={signer_address}, delegate_adr={delegate_adr}klasssigner_addressdelegate_adrxbr.error.invalid_signatureO{}.sell()::XBRSIG[4/8] - EIP712 signature invalid or not signed by market maker)r   r_   r`   is_finalr   z{klass}.close_channel() - {tx_type} closing channel {channel_adr}, closing balance {channel_balance}, closing sequence {channel_seq} [caller={caller}, caller_authid="{caller_authid}"]zXBR CLOSE  rC   rD   r   r   )r   rG   channel_balancechannel_seqchannel_adrcallercaller_authid)!r   r   r   re   r   boolr   r   rk   r   	__class__rT   r   r   r   rx   r{   leaver\   r   r]   r   rO   r   r   r   rl   rt   r	   rP   rf   r   r   )r   r}   r   r   r   channel_is_finalmarketmaker_signaturer   r   seller_signaturereceiptr"   r"   r#   r     sd   ****
&
*



	zSimpleSeller.close_channelc
                 C   s  t |tkrt|dksJ dt |tkrt|dks J dt |tkr,t|dks0J dt |tkr<t|dks@J dt |tksJJ dt |tkrVt|dks_J d	t |t |tkrkt|dkstJ d
t |t |tkrt|dksJ d|	du st|	tsJ dt|}t|}|| jkrt	dd| j
jt| j t| || jvrt	dd| j
j|| j| }
|| jd kr| j  t	dd| j
jt| jd  t| || jd krt	dd| j
j| jd ||| j| krt	dd| j
j| j| |t|||d|}||krN| jjd| j
jtt| tt| d t	dd| j
j|  jd7  _|  j|8  _|
||}t |tkrpt|d kszJ d!| j
j|t| j| jd | j| j}|| j||| j|| j|d"}| jjd#| j
jtd$d%d&ttj|d'tt t|d( d) d%d&tt t| jd( d) d%d&t|	j!t|	j"tt| d*	 |S )+al  
        Called by a XBR Market Maker to buy a data encyption key. The XBR Market Maker here is
        acting for (triggered by) the XBR buyer delegate.

        :param market_maker_adr: The market maker Ethereum address. The technical buyer is usually the
            XBR market maker (== the XBR delegate of the XBR market operator).
        :type market_maker_adr: bytes of length 20

        :param buyer_pubkey: The buyer delegate Ed25519 public key.
        :type buyer_pubkey: bytes of length 32

        :param key_id: The UUID of the data encryption key to buy.
        :type key_id: bytes of length 16

        :param channel_adr: The on-chain channel contract address.
        :type channel_adr: bytes of length 20

        :param channel_seq: Paying channel sequence off-chain transaction number.
        :type channel_seq: int

        :param amount: The amount paid by the XBR Buyer via the XBR Market Maker.
        :type amount: bytes

        :param balance: Balance remaining in the payment channel (from the market maker to the
            seller) after successfully buying the key.
        :type balance: bytes

        :param signature: Signature over the supplied buying information, using the Ethereum
            private key of the market maker (which is the delegate of the marker operator).
        :type signature: bytes of length 65

        :param details: Caller details. The call will come from the XBR Market Maker.
        :type details: :class:`autobahn.wamp.types.CallDetails`

        :return: The data encryption key, itself encrypted to the public key of the original buyer.
        :rtype: bytes
        rZ   zdelegate_adr must be bytes[20]r.   zbuyer_pubkey must be bytes[32]r   zkey_id must be bytes[16]zchannel_adr must be bytes[20]zchannel_seq must be intz)amount_paid must be bytes[32], but was {}z*post_balance must be bytes[32], but was {}r   zsignature must be bytes[65]Nr   z$xbr.error.unexpected_marketmaker_adrzH{}.sell() - unexpected market maker address: expected 0x{}, but got 0x{}zcrossbar.error.no_such_objectz{}.sell() - no key with ID "{}"r   r   r   r   r   r   r   r   Fr   r   r   r   P   zC{}.sell() - unexpected sealed key computed (expected bytes[80]): {})r&   r   r6   
sealed_keyr   amountr`   r   z{klass}.sell() - {tx_type} key "{key_id}" sold for {amount_earned} - balance is {balance} [caller={caller}, caller_authid="{caller_authid}", buyer_pubkey="{buyer_pubkey}"]z
XBR SELL  rC   rD   rF   r   r   )r   rG   r&   amount_earnedr`   r   r   r6   )#r   r   r   r   re   r   r   r   rk   r   r   rT   r   r   r   rz   rx   r{   r   r\   r]   r   rO   r   r   r;   r   rl   rt   rP   rQ   rR   rf   r   r   )r   r}   r6   r&   r   r   r   r`   r   r   r   r   r   r   r   r"   r"   r#   r   #  s    &   ** 
&


*
0
zSimpleSeller.sellr=   )rT   rU   rV   rO   r   ri   r   r   r   r   r$   rX   rr   r   r@   rB   r`   r   r   r   r"   r"   r"   r#   ra      s&    
A

	U7
Bra   )r   r   rH   rQ   autobahn.wamp.typesr   r   autobahn.wamp.exceptionr   r   autobahn.wamp.protocolr   _utilr   r	   zlmdbr
   r(   rm   nacl.secretr0   
nacl.utilsnacl.publicrg   r   r   r   objectr   rY   ra   r"   r"   r"   r#   <module>   s&   v
