Add PARTct to coin code.
This commit is contained in:
		
							parent
							
								
									2a3d89b112
								
							
						
					
					
						commit
						c4321b7740
					
				@ -4765,7 +4765,7 @@ class BasicSwap(BaseApp):
 | 
				
			|||||||
            self.logBidEvent(bid.bid_id, EventLogTypes.DEBUG_TWEAK_APPLIED, 'ind {}'.format(bid.debug_ind), session)
 | 
					            self.logBidEvent(bid.bid_id, EventLogTypes.DEBUG_TWEAK_APPLIED, 'ind {}'.format(bid.debug_ind), session)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            b_lock_tx_id = ci_to.publishBLockTx(xmr_swap.pkbv, xmr_swap.pkbs, bid.amount_to, xmr_offer.b_fee_rate, unlock_time=unlock_time)
 | 
					            b_lock_tx_id = ci_to.publishBLockTx(xmr_swap.vkbv, xmr_swap.pkbs, bid.amount_to, xmr_offer.b_fee_rate, unlock_time=unlock_time)
 | 
				
			||||||
            if bid.debug_ind == DebugTypes.B_LOCK_TX_MISSED_SEND:
 | 
					            if bid.debug_ind == DebugTypes.B_LOCK_TX_MISSED_SEND:
 | 
				
			||||||
                self.log.debug('XMR bid %s: Debug %d - Losing xmr lock tx %s.', bid_id.hex(), bid.debug_ind, b_lock_tx_id.hex())
 | 
					                self.log.debug('XMR bid %s: Debug %d - Losing xmr lock tx %s.', bid_id.hex(), bid.debug_ind, b_lock_tx_id.hex())
 | 
				
			||||||
                self.logBidEvent(bid.bid_id, EventLogTypes.DEBUG_TWEAK_APPLIED, 'ind {}'.format(bid.debug_ind), session)
 | 
					                self.logBidEvent(bid.bid_id, EventLogTypes.DEBUG_TWEAK_APPLIED, 'ind {}'.format(bid.debug_ind), session)
 | 
				
			||||||
 | 
				
			|||||||
@ -987,7 +987,7 @@ class BTCInterface(CoinInterface):
 | 
				
			|||||||
        tx = self.loadTx(tx_bytes)
 | 
					        tx = self.loadTx(tx_bytes)
 | 
				
			||||||
        return tx.wit.vtxinwit[0].scriptWitness.stack[2]
 | 
					        return tx.wit.vtxinwit[0].scriptWitness.stack[2]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def createBLockTx(self, Kbs, output_amount):
 | 
					    def createBLockTx(self, Kbs, output_amount, vkbv=None) -> bytes:
 | 
				
			||||||
        tx = CTransaction()
 | 
					        tx = CTransaction()
 | 
				
			||||||
        tx.nVersion = self.txVersion()
 | 
					        tx.nVersion = self.txVersion()
 | 
				
			||||||
        p2wpkh_script_pk = self.getPkDest(Kbs)
 | 
					        p2wpkh_script_pk = self.getPkDest(Kbs)
 | 
				
			||||||
@ -997,7 +997,7 @@ class BTCInterface(CoinInterface):
 | 
				
			|||||||
    def encodeSharedAddress(self, Kbv, Kbs):
 | 
					    def encodeSharedAddress(self, Kbv, Kbs):
 | 
				
			||||||
        return self.pubkey_to_segwit_address(Kbs)
 | 
					        return self.pubkey_to_segwit_address(Kbs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def publishBLockTx(self, Kbv, Kbs, output_amount, feerate, delay_for: int = 10, unlock_time: int = 0) -> bytes:
 | 
					    def publishBLockTx(self, kbv, Kbs, output_amount, feerate, delay_for: int = 10, unlock_time: int = 0) -> bytes:
 | 
				
			||||||
        b_lock_tx = self.createBLockTx(Kbs, output_amount)
 | 
					        b_lock_tx = self.createBLockTx(Kbs, output_amount)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        b_lock_tx = self.fundTx(b_lock_tx, feerate)
 | 
					        b_lock_tx = self.fundTx(b_lock_tx, feerate)
 | 
				
			||||||
 | 
				
			|||||||
@ -625,6 +625,122 @@ class PARTInterfaceBlind(PARTInterface):
 | 
				
			|||||||
    def getSpendableBalance(self):
 | 
					    def getSpendableBalance(self):
 | 
				
			||||||
        return self.make_int(self.rpc_callback('getbalances')['mine']['blind_trusted'])
 | 
					        return self.make_int(self.rpc_callback('getbalances')['mine']['blind_trusted'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def publishBLockTx(self, vkbv, Kbs, output_amount, feerate, delay_for: int = 10, unlock_time: int = 0) -> bytes:
 | 
				
			||||||
 | 
					        Kbv = self.getPubkey(vkbv)
 | 
				
			||||||
 | 
					        sx_addr = self.formatStealthAddress(Kbv, Kbs)
 | 
				
			||||||
 | 
					        self._log.debug('sx_addr: {}'.format(sx_addr))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # TODO: Fund from other balances
 | 
				
			||||||
 | 
					        params = ['blind', 'blind',
 | 
				
			||||||
 | 
					                  [{'address': sx_addr, 'amount': self.format_amount(output_amount)}, ],
 | 
				
			||||||
 | 
					                  '', '', self._anon_tx_ring_size, 1, False,
 | 
				
			||||||
 | 
					                  {'conf_target': self._conf_target, 'blind_watchonly_visible': True}]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        txid = self.rpc_callback('sendtypeto', params)
 | 
				
			||||||
 | 
					        return bytes.fromhex(txid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def findTxB(self, kbv, Kbs, cb_swap_value, cb_block_confirmed, restore_height, bid_sender):
 | 
				
			||||||
 | 
					        Kbv = self.getPubkey(kbv)
 | 
				
			||||||
 | 
					        sx_addr = self.formatStealthAddress(Kbv, Kbs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Tx recipient must import the stealth address as watch only
 | 
				
			||||||
 | 
					        if bid_sender:
 | 
				
			||||||
 | 
					            cb_swap_value *= -1
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            addr_info = self.rpc_callback('getaddressinfo', [sx_addr])
 | 
				
			||||||
 | 
					            if not addr_info['iswatchonly']:
 | 
				
			||||||
 | 
					                wif_prefix = self.chainparams_network()['key_prefix']
 | 
				
			||||||
 | 
					                wif_scan_key = toWIF(wif_prefix, kbv)
 | 
				
			||||||
 | 
					                self.rpc_callback('importstealthaddress', [wif_scan_key, Kbs.hex()])
 | 
				
			||||||
 | 
					                self._log.info('Imported watch-only sx_addr: {}'.format(sx_addr))
 | 
				
			||||||
 | 
					                self._log.info('Rescanning {} chain from height: {}'.format(self.coin_name(), restore_height))
 | 
				
			||||||
 | 
					                self.rpc_callback('rescanblockchain', [restore_height])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        params = [{'include_watchonly': True, 'search': sx_addr}]
 | 
				
			||||||
 | 
					        txns = self.rpc_callback('filtertransactions', params)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if len(txns) == 1:
 | 
				
			||||||
 | 
					            tx = txns[0]
 | 
				
			||||||
 | 
					            assert (tx['outputs'][0]['stealth_address'] == sx_addr)  # Should not be possible
 | 
				
			||||||
 | 
					            ensure(tx['outputs'][0]['type'] == 'blind', 'Output is not anon')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if make_int(tx['outputs'][0]['amount']) == cb_swap_value:
 | 
				
			||||||
 | 
					                height = 0
 | 
				
			||||||
 | 
					                if tx['confirmations'] > 0:
 | 
				
			||||||
 | 
					                    chain_height = self.rpc_callback('getblockcount')
 | 
				
			||||||
 | 
					                    height = chain_height - (tx['confirmations'] - 1)
 | 
				
			||||||
 | 
					                return {'txid': tx['txid'], 'amount': cb_swap_value, 'height': height}
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                self._log.warning('Incorrect amount detected for coin b lock txn: {}'.format(tx['txid']))
 | 
				
			||||||
 | 
					                return -1
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def spendBLockTx(self, chain_b_lock_txid, address_to, kbv, kbs, cb_swap_value, b_fee, restore_height, spend_actual_balance=False):
 | 
				
			||||||
 | 
					        Kbv = self.getPubkey(kbv)
 | 
				
			||||||
 | 
					        Kbs = self.getPubkey(kbs)
 | 
				
			||||||
 | 
					        sx_addr = self.formatStealthAddress(Kbv, Kbs)
 | 
				
			||||||
 | 
					        addr_info = self.rpc_callback('getaddressinfo', [sx_addr])
 | 
				
			||||||
 | 
					        if not addr_info['ismine']:
 | 
				
			||||||
 | 
					            wif_prefix = self.chainparams_network()['key_prefix']
 | 
				
			||||||
 | 
					            wif_scan_key = toWIF(wif_prefix, kbv)
 | 
				
			||||||
 | 
					            wif_spend_key = toWIF(wif_prefix, kbs)
 | 
				
			||||||
 | 
					            self.rpc_callback('importstealthaddress', [wif_scan_key, wif_spend_key])
 | 
				
			||||||
 | 
					            self._log.info('Imported spend key for sx_addr: {}'.format(sx_addr))
 | 
				
			||||||
 | 
					            self._log.info('Rescanning {} chain from height: {}'.format(self.coin_name(), restore_height))
 | 
				
			||||||
 | 
					            self.rpc_callback('rescanblockchain', [restore_height])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # TODO: Remove workaround
 | 
				
			||||||
 | 
					        # utxos = self.rpc_callback('listunspentblind', [1, 9999999, [sx_addr]])
 | 
				
			||||||
 | 
					        utxos = []
 | 
				
			||||||
 | 
					        all_utxos = self.rpc_callback('listunspentblind', [1, 9999999])
 | 
				
			||||||
 | 
					        for utxo in all_utxos:
 | 
				
			||||||
 | 
					            if utxo.get('stealth_address', '_') == sx_addr:
 | 
				
			||||||
 | 
					                utxos.append(utxo)
 | 
				
			||||||
 | 
					        if len(utxos) < 1:
 | 
				
			||||||
 | 
					            raise TemporaryError('No spendable outputs')
 | 
				
			||||||
 | 
					        elif len(utxos) > 1:
 | 
				
			||||||
 | 
					            raise ValueError('Too many spendable outputs')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        utxo = utxos[0]
 | 
				
			||||||
 | 
					        utxo_sats = make_int(utxo['amount'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if spend_actual_balance and utxo_sats != cb_swap_value:
 | 
				
			||||||
 | 
					            self._log.warning('Spending actual balance {}, not swap value {}.'.format(utxo_sats, cb_swap_value))
 | 
				
			||||||
 | 
					            cb_swap_value = utxo_sats
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inputs = [{'tx': utxo['txid'], 'n': utxo['vout']}, ]
 | 
				
			||||||
 | 
					        params = ['blind', 'blind',
 | 
				
			||||||
 | 
					                  [{'address': address_to, 'amount': self.format_amount(cb_swap_value), 'subfee': True}, ],
 | 
				
			||||||
 | 
					                  '', '', self._anon_tx_ring_size, 1, False,
 | 
				
			||||||
 | 
					                  {'conf_target': self._conf_target, 'inputs': inputs, 'show_fee': True}]
 | 
				
			||||||
 | 
					        rv = self.rpc_callback('sendtypeto', params)
 | 
				
			||||||
 | 
					        return bytes.fromhex(rv['txid'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def findTxnByHash(self, txid_hex):
 | 
				
			||||||
 | 
					        # txindex is enabled for Particl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            rv = self.rpc_callback('getrawtransaction', [txid_hex, True])
 | 
				
			||||||
 | 
					        except Exception as ex:
 | 
				
			||||||
 | 
					            self._log.debug('findTxnByHash getrawtransaction failed: {}'.format(txid_hex))
 | 
				
			||||||
 | 
					            return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if 'confirmations' in rv and rv['confirmations'] >= self.blocks_confirmed:
 | 
				
			||||||
 | 
					            return {'txid': txid_hex, 'amount': 0, 'height': rv['height']}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def createRawFundedTransaction(self, addr_to: str, amount: int, sub_fee: bool = False, lock_unspents: bool = True) -> str:
 | 
				
			||||||
 | 
					        txn = self.rpc_callback('createrawtransaction', [[], {addr_to: self.format_amount(amount)}])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        options = {
 | 
				
			||||||
 | 
					            'lockUnspents': lock_unspents,
 | 
				
			||||||
 | 
					            'conf_target': self._conf_target,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if sub_fee:
 | 
				
			||||||
 | 
					            options['subtractFeeFromOutputs'] = [0,]
 | 
				
			||||||
 | 
					        return self.rpc_callback('fundrawtransactionfrom', ['blind', txn, options])['hex']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PARTInterfaceAnon(PARTInterface):
 | 
					class PARTInterfaceAnon(PARTInterface):
 | 
				
			||||||
    @staticmethod
 | 
					    @staticmethod
 | 
				
			||||||
@ -638,9 +754,9 @@ class PARTInterfaceAnon(PARTInterface):
 | 
				
			|||||||
    def coin_name(self):
 | 
					    def coin_name(self):
 | 
				
			||||||
        return super().coin_name() + ' Anon'
 | 
					        return super().coin_name() + ' Anon'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def publishBLockTx(self, Kbv, Kbs, output_amount, feerate, delay_for: int = 10, unlock_time: int = 0) -> bytes:
 | 
					    def publishBLockTx(self, kbv, Kbs, output_amount, feerate, delay_for: int = 10, unlock_time: int = 0) -> bytes:
 | 
				
			||||||
 | 
					        Kbv = self.getPubkey(kbv)
 | 
				
			||||||
        sx_addr = self.formatStealthAddress(Kbv, Kbs)
 | 
					        sx_addr = self.formatStealthAddress(Kbv, Kbs)
 | 
				
			||||||
        self._log.debug('sx_addr: {}'.format(sx_addr))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # TODO: Fund from other balances
 | 
					        # TODO: Fund from other balances
 | 
				
			||||||
        params = ['anon', 'anon',
 | 
					        params = ['anon', 'anon',
 | 
				
			||||||
 | 
				
			|||||||
@ -258,11 +258,12 @@ class XMRInterface(CoinInterface):
 | 
				
			|||||||
    def encodeSharedAddress(self, Kbv, Kbs):
 | 
					    def encodeSharedAddress(self, Kbv, Kbs):
 | 
				
			||||||
        return xmr_util.encode_address(Kbv, Kbs)
 | 
					        return xmr_util.encode_address(Kbv, Kbs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def publishBLockTx(self, Kbv, Kbs, output_amount, feerate, delay_for: int = 10, unlock_time: int = 0) -> bytes:
 | 
					    def publishBLockTx(self, kbv, Kbs, output_amount, feerate, delay_for: int = 10, unlock_time: int = 0) -> bytes:
 | 
				
			||||||
        with self._mx_wallet:
 | 
					        with self._mx_wallet:
 | 
				
			||||||
            self.openWallet(self._wallet_filename)
 | 
					            self.openWallet(self._wallet_filename)
 | 
				
			||||||
            self.rpc_wallet_cb('refresh')
 | 
					            self.rpc_wallet_cb('refresh')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Kbv = self.getPubkey(kbv)
 | 
				
			||||||
            shared_addr = xmr_util.encode_address(Kbv, Kbs)
 | 
					            shared_addr = xmr_util.encode_address(Kbv, Kbs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            params = {'destinations': [{'amount': output_amount, 'address': shared_addr}], 'unlock_time': unlock_time}
 | 
					            params = {'destinations': [{'amount': output_amount, 'address': shared_addr}], 'unlock_time': unlock_time}
 | 
				
			||||||
 | 
				
			|||||||
@ -473,7 +473,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    function set_swap_type_enabled(coin_from, coin_to, swap_type) {
 | 
					    function set_swap_type_enabled(coin_from, coin_to, swap_type) {
 | 
				
			||||||
      let make_hidden = false;
 | 
					      let make_hidden = false;
 | 
				
			||||||
      if (coin_to == '6' /* XMR */ || coin_to == '8' /* PART_ANON */) {
 | 
					      if (coin_to == '6' /* XMR */ || coin_to == '8' /* PART_ANON */ || coin_to == '7' /* PART_BLIND */ || coin_from == '7' /* PART_BLIND */) {
 | 
				
			||||||
        swap_type.disabled = true;
 | 
					        swap_type.disabled = true;
 | 
				
			||||||
        swap_type.value = 'xmr_swap';
 | 
					        swap_type.value = 'xmr_swap';
 | 
				
			||||||
        make_hidden = true;
 | 
					        make_hidden = true;
 | 
				
			||||||
@ -486,12 +486,8 @@
 | 
				
			|||||||
        swap_type.disabled = false;
 | 
					        swap_type.disabled = false;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      let swap_type_hidden = document.getElementById('swap_type_hidden');
 | 
					      let swap_type_hidden = document.getElementById('swap_type_hidden');
 | 
				
			||||||
      console.log('make_hidden', make_hidden);
 | 
					 | 
				
			||||||
      console.log('swap_type_hidden', swap_type_hidden);
 | 
					 | 
				
			||||||
      console.log('swap_type.value', swap_type.value);
 | 
					 | 
				
			||||||
      if (make_hidden) {
 | 
					      if (make_hidden) {
 | 
				
			||||||
        if (!swap_type_hidden) {
 | 
					        if (!swap_type_hidden) {
 | 
				
			||||||
          console.log('createElement');
 | 
					 | 
				
			||||||
          swap_type_hidden = document.createElement('input');
 | 
					          swap_type_hidden = document.createElement('input');
 | 
				
			||||||
          swap_type_hidden.setAttribute('id', 'swap_type_hidden');
 | 
					          swap_type_hidden.setAttribute('id', 'swap_type_hidden');
 | 
				
			||||||
          swap_type_hidden.setAttribute('type', 'hidden');
 | 
					          swap_type_hidden.setAttribute('type', 'hidden');
 | 
				
			||||||
@ -501,7 +497,6 @@
 | 
				
			|||||||
        swap_type_hidden.setAttribute('value', swap_type.value);
 | 
					        swap_type_hidden.setAttribute('value', swap_type.value);
 | 
				
			||||||
      } else
 | 
					      } else
 | 
				
			||||||
      if (swap_type_hidden) {
 | 
					      if (swap_type_hidden) {
 | 
				
			||||||
        console.log('remove element');
 | 
					 | 
				
			||||||
        swap_type_hidden.parentNode.removeChild(swap_type_hidden);
 | 
					        swap_type_hidden.parentNode.removeChild(swap_type_hidden);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -34,6 +34,7 @@ from tests.basicswap.common import (
 | 
				
			|||||||
    wait_for_offer,
 | 
					    wait_for_offer,
 | 
				
			||||||
    wait_for_none_active,
 | 
					    wait_for_none_active,
 | 
				
			||||||
    wait_for_balance,
 | 
					    wait_for_balance,
 | 
				
			||||||
 | 
					    wait_for_unspent,
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .test_xmr import BaseTest, test_delay_event
 | 
					from .test_xmr import BaseTest, test_delay_event
 | 
				
			||||||
@ -43,6 +44,8 @@ logger = logging.getLogger()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class Test(BaseTest):
 | 
					class Test(BaseTest):
 | 
				
			||||||
    __test__ = True
 | 
					    __test__ = True
 | 
				
			||||||
 | 
					    test_coin_from = Coins.PART_BLIND
 | 
				
			||||||
 | 
					    has_segwit = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def setUpClass(cls):
 | 
					    def setUpClass(cls):
 | 
				
			||||||
@ -65,6 +68,21 @@ class Test(BaseTest):
 | 
				
			|||||||
        js_0 = read_json_api(1800, 'wallets/part')
 | 
					        js_0 = read_json_api(1800, 'wallets/part')
 | 
				
			||||||
        node0_blind_before = js_0['blind_balance'] + js_0['blind_unconfirmed']
 | 
					        node0_blind_before = js_0['blind_balance'] + js_0['blind_unconfirmed']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def ensure_balance(self, coin_type, node_id, amount):
 | 
				
			||||||
 | 
					        tla = 'PART'
 | 
				
			||||||
 | 
					        js_w = read_json_api(1800 + node_id, 'wallets')
 | 
				
			||||||
 | 
					        print('js_w', js_w)
 | 
				
			||||||
 | 
					        if float(js_w[tla]['blind_balance']) < amount:
 | 
				
			||||||
 | 
					            post_json = {
 | 
				
			||||||
 | 
					                'value': amount,
 | 
				
			||||||
 | 
					                'type_to': 'blind',
 | 
				
			||||||
 | 
					                'address': js_w[tla]['stealth_address'],
 | 
				
			||||||
 | 
					                'subfee': False,
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            json_rv = read_json_api(1800, 'wallets/{}/withdraw'.format(tla.lower()), post_json)
 | 
				
			||||||
 | 
					            assert (len(json_rv['txid']) == 64)
 | 
				
			||||||
 | 
					            wait_for_balance(test_delay_event, 'http://127.0.0.1:{}/json/wallets/{}'.format(1800 + node_id, tla.lower()), 'blind_balance', amount)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getBalance(self, js_wallets):
 | 
					    def getBalance(self, js_wallets):
 | 
				
			||||||
        return float(js_wallets[Coins.PART.name]['blind_balance']) + float(js_wallets[Coins.PART.name]['blind_unconfirmed'])
 | 
					        return float(js_wallets[Coins.PART.name]['blind_balance']) + float(js_wallets[Coins.PART.name]['blind_unconfirmed'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -208,18 +226,17 @@ class Test(BaseTest):
 | 
				
			|||||||
        redeemed_txid = json.loads(urlopen('http://127.0.0.1:1801/json/bids/{}'.format(bid_id.hex()), data=data).read())['txid']
 | 
					        redeemed_txid = json.loads(urlopen('http://127.0.0.1:1801/json/bids/{}'.format(bid_id.hex()), data=data).read())['txid']
 | 
				
			||||||
        assert (len(redeemed_txid) == 64)
 | 
					        assert (len(redeemed_txid) == 64)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_04_follower_recover_b_lock_tx(self):
 | 
					    def do_test_04_follower_recover_b_lock_tx(self, coin_from, coin_to):
 | 
				
			||||||
        logging.info('---------- Test PARTct to XMR follower recovers coin b lock tx')
 | 
					        logging.info('---------- Test {} to {} follower recovers coin b lock tx'.format(coin_from.name, coin_to.name))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        swap_clients = self.swap_clients
 | 
					        swap_clients = self.swap_clients
 | 
				
			||||||
 | 
					        ci_from = swap_clients[0].ci(coin_from)
 | 
				
			||||||
 | 
					        ci_to = swap_clients[0].ci(coin_to)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        js_w0_before = read_json_api(1800, 'wallets')
 | 
					        amt_swap = ci_from.make_int(random.uniform(0.1, 2.0), r=1)
 | 
				
			||||||
        js_w1_before = read_json_api(1801, 'wallets')
 | 
					        rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
 | 
				
			||||||
 | 
					 | 
				
			||||||
        amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1)
 | 
					 | 
				
			||||||
        rate_swap = make_int(random.uniform(0.2, 20.0), scale=12, r=1)
 | 
					 | 
				
			||||||
        offer_id = swap_clients[0].postOffer(
 | 
					        offer_id = swap_clients[0].postOffer(
 | 
				
			||||||
            Coins.PART_BLIND, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP,
 | 
					            coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP,
 | 
				
			||||||
            lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=28)
 | 
					            lock_type=TxLockTypes.SEQUENCE_LOCK_BLOCKS, lock_value=28)
 | 
				
			||||||
        wait_for_offer(test_delay_event, swap_clients[1], offer_id)
 | 
					        wait_for_offer(test_delay_event, swap_clients[1], offer_id)
 | 
				
			||||||
        offer = swap_clients[1].getOffer(offer_id)
 | 
					        offer = swap_clients[1].getOffer(offer_id)
 | 
				
			||||||
@ -238,9 +255,13 @@ class Test(BaseTest):
 | 
				
			|||||||
        wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=180)
 | 
					        wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, wait_for=180)
 | 
				
			||||||
        wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=True)
 | 
					        wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.XMR_SWAP_FAILED_REFUNDED, sent=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_04_follower_recover_b_lock_tx(self):
 | 
				
			||||||
 | 
					        js_w0_before = read_json_api(1800, 'wallets')
 | 
				
			||||||
 | 
					        js_w1_before = read_json_api(1801, 'wallets')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.do_test_04_follower_recover_b_lock_tx(self.test_coin_from, Coins.XMR)
 | 
				
			||||||
        js_w0_after = read_json_api(1800, 'wallets')
 | 
					        js_w0_after = read_json_api(1800, 'wallets')
 | 
				
			||||||
        js_w1_after = read_json_api(1801, 'wallets')
 | 
					        js_w1_after = read_json_api(1801, 'wallets')
 | 
				
			||||||
 | 
					 | 
				
			||||||
        node0_blind_before = self.getBalance(js_w0_before)
 | 
					        node0_blind_before = self.getBalance(js_w0_before)
 | 
				
			||||||
        node0_blind_after = self.getBalance(js_w0_after)
 | 
					        node0_blind_after = self.getBalance(js_w0_after)
 | 
				
			||||||
        assert (node0_blind_before - node0_blind_after < 0.02)
 | 
					        assert (node0_blind_before - node0_blind_after < 0.02)
 | 
				
			||||||
@ -249,6 +270,102 @@ class Test(BaseTest):
 | 
				
			|||||||
        node1_xmr_after = self.getXmrBalance(js_w1_after)
 | 
					        node1_xmr_after = self.getXmrBalance(js_w1_after)
 | 
				
			||||||
        assert (node1_xmr_before - node1_xmr_after < 0.02)
 | 
					        assert (node1_xmr_before - node1_xmr_after < 0.02)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_04_follower_recover_b_lock_tx_from_part(self):
 | 
				
			||||||
 | 
					        self.ensure_balance(self.test_coin_from, 1, 50.0)
 | 
				
			||||||
 | 
					        self.do_test_04_follower_recover_b_lock_tx(Coins.PART, self.test_coin_from)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def do_test_05_self_bid(self, coin_from, coin_to):
 | 
				
			||||||
 | 
					        logging.info('---------- Test {} to {} same client'.format(coin_from.name, coin_to.name))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        swap_clients = self.swap_clients
 | 
				
			||||||
 | 
					        ci_to = swap_clients[0].ci(coin_to)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.ensure_balance(coin_from, 1, 50.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1)
 | 
				
			||||||
 | 
					        rate_swap = ci_to.make_int(random.uniform(0.2, 20.0), r=1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        offer_id = swap_clients[1].postOffer(coin_from, coin_to, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, auto_accept_bids=True)
 | 
				
			||||||
 | 
					        bid_id = swap_clients[1].postXmrBid(offer_id, amt_swap)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, wait_for=180)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_05_self_bid(self):
 | 
				
			||||||
 | 
					        if not self.has_segwit:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        self.do_test_05_self_bid(self.test_coin_from, Coins.XMR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_05_self_bid_to_part(self):
 | 
				
			||||||
 | 
					        if not self.has_segwit:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        self.do_test_05_self_bid(self.test_coin_from, Coins.PART)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_05_self_bid_from_part(self):
 | 
				
			||||||
 | 
					        self.do_test_05_self_bid(Coins.PART, self.test_coin_from)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_06_preselect_inputs(self):
 | 
				
			||||||
 | 
					        raise ValueError('TODO')
 | 
				
			||||||
 | 
					        tla_from = self.test_coin_from.name
 | 
				
			||||||
 | 
					        logging.info('---------- Test {} Preselected inputs'.format(tla_from))
 | 
				
			||||||
 | 
					        swap_clients = self.swap_clients
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Prepare balance
 | 
				
			||||||
 | 
					        self.ensure_balance(self.test_coin_from, 2, 100.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        js_w2 = read_json_api(1802, 'wallets')
 | 
				
			||||||
 | 
					        print('[rm] js_w2', js_w2)
 | 
				
			||||||
 | 
					        post_json = {
 | 
				
			||||||
 | 
					            'value': float(js_w2['PART']['blind_balance']),
 | 
				
			||||||
 | 
					            'type_from': 'blind',
 | 
				
			||||||
 | 
					            'type_to': 'blind',
 | 
				
			||||||
 | 
					            'address': js_w2['PART']['stealth_address'],
 | 
				
			||||||
 | 
					            'subfee': True,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        json_rv = read_json_api(1802, 'wallets/{}/withdraw'.format('part'), post_json)
 | 
				
			||||||
 | 
					        wait_for_balance(test_delay_event, 'http://127.0.0.1:1802/json/wallets/{}'.format('part'), 'blind_balance', 10.0)
 | 
				
			||||||
 | 
					        assert (len(json_rv['txid']) == 64)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Create prefunded ITX
 | 
				
			||||||
 | 
					        ci = swap_clients[2].ci(self.test_coin_from)
 | 
				
			||||||
 | 
					        ci_to = swap_clients[2].ci(Coins.XMR)
 | 
				
			||||||
 | 
					        pi = swap_clients[2].pi(SwapTypes.XMR_SWAP)
 | 
				
			||||||
 | 
					        js_w2 = read_json_api(1802, 'wallets')
 | 
				
			||||||
 | 
					        swap_value = ci.make_int(js_w2['PART']['blind_balance'])
 | 
				
			||||||
 | 
					        assert (swap_value > ci.make_int(95))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        itx = pi.getFundedInitiateTxTemplate(ci, swap_value, True)
 | 
				
			||||||
 | 
					        itx_decoded = ci.describeTx(itx.hex())
 | 
				
			||||||
 | 
					        n = pi.findMockVout(ci, itx_decoded)
 | 
				
			||||||
 | 
					        value_after_subfee = ci.make_int(itx_decoded['vout'][n]['value'])
 | 
				
			||||||
 | 
					        assert (value_after_subfee < swap_value)
 | 
				
			||||||
 | 
					        swap_value = value_after_subfee
 | 
				
			||||||
 | 
					        wait_for_unspent(test_delay_event, ci, swap_value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        extra_options = {'prefunded_itx': itx}
 | 
				
			||||||
 | 
					        rate_swap = ci_to.make_int(random.uniform(0.2, 20.0))
 | 
				
			||||||
 | 
					        offer_id = swap_clients[2].postOffer(self.test_coin_from, Coins.XMR, swap_value, rate_swap, swap_value, SwapTypes.XMR_SWAP, extra_options=extra_options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        wait_for_offer(test_delay_event, swap_clients[1], offer_id)
 | 
				
			||||||
 | 
					        offer = swap_clients[1].getOffer(offer_id)
 | 
				
			||||||
 | 
					        bid_id = swap_clients[1].postBid(offer_id, offer.amount_from)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        wait_for_bid(test_delay_event, swap_clients[2], bid_id, BidStates.BID_RECEIVED)
 | 
				
			||||||
 | 
					        swap_clients[2].acceptBid(bid_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        wait_for_bid(test_delay_event, swap_clients[2], bid_id, BidStates.SWAP_COMPLETED, wait_for=120)
 | 
				
			||||||
 | 
					        wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True, wait_for=120)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Verify expected inputs were used
 | 
				
			||||||
 | 
					        bid, _, _, _, _ = swap_clients[2].getXmrBidAndOffer(bid_id)
 | 
				
			||||||
 | 
					        assert (bid.xmr_a_lock_tx)
 | 
				
			||||||
 | 
					        wtx = ci.rpc_callback('gettransaction', [bid.xmr_a_lock_tx.txid.hex(),])
 | 
				
			||||||
 | 
					        itx_after = ci.describeTx(wtx['hex'])
 | 
				
			||||||
 | 
					        assert (len(itx_after['vin']) == len(itx_decoded['vin']))
 | 
				
			||||||
 | 
					        for i, txin in enumerate(itx_decoded['vin']):
 | 
				
			||||||
 | 
					            txin_after = itx_after['vin'][i]
 | 
				
			||||||
 | 
					            assert (txin['txid'] == txin_after['txid'])
 | 
				
			||||||
 | 
					            assert (txin['vout'] == txin_after['vout'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if __name__ == '__main__':
 | 
					if __name__ == '__main__':
 | 
				
			||||||
    unittest.main()
 | 
					    unittest.main()
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user