ui: Expose offer valid time.
This commit is contained in:
		
							parent
							
								
									f2018184e7
								
							
						
					
					
						commit
						36a40b5fa3
					
				@ -870,7 +870,7 @@ class BasicSwap(BaseApp):
 | 
			
		||||
            ci.initialiseWallet(key_view, key_spend)
 | 
			
		||||
            root_address = ci.getAddressFromKeys(key_view, key_spend)
 | 
			
		||||
 | 
			
		||||
            key_str = 'main_wallet_addr_' + chainparams[coin_type]['name']
 | 
			
		||||
            key_str = 'main_wallet_addr_' + ci.coin_name()
 | 
			
		||||
            self.setStringKV(key_str, root_address)
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
@ -878,7 +878,7 @@ class BasicSwap(BaseApp):
 | 
			
		||||
        root_hash = ci.getAddressHashFromKey(root_key)[::-1]
 | 
			
		||||
        ci.initialiseWallet(root_key)
 | 
			
		||||
 | 
			
		||||
        key_str = 'main_wallet_seedid_' + chainparams[coin_type]['name']
 | 
			
		||||
        key_str = 'main_wallet_seedid_' + ci.coin_name()
 | 
			
		||||
        self.setStringKV(key_str, root_hash.hex())
 | 
			
		||||
 | 
			
		||||
    def setIntKVInSession(self, str_key, int_val, session):
 | 
			
		||||
@ -1101,6 +1101,12 @@ class BasicSwap(BaseApp):
 | 
			
		||||
        else:
 | 
			
		||||
            raise ValueError('Unknown locktype')
 | 
			
		||||
 | 
			
		||||
    def validateOfferValidTime(self, coin_from, coin_to, valid_for_seconds):
 | 
			
		||||
        if valid_for_seconds < 60 * 60:  # SMSG_MIN_TTL
 | 
			
		||||
            raise ValueError('Offer TTL too low')
 | 
			
		||||
        if valid_for_seconds > 48 * 60 * 60:
 | 
			
		||||
            raise ValueError('Offer TTL too high')
 | 
			
		||||
 | 
			
		||||
    def postOffer(self, coin_from, coin_to, amount, rate, min_bid_amount, swap_type,
 | 
			
		||||
                  lock_type=SEQUENCE_LOCK_TIME, lock_value=48 * 60 * 60, auto_accept_bids=False, addr_send_from=None, extra_options={}):
 | 
			
		||||
        # Offer to send offer.amount_from of coin_from in exchange for offer.amount_from * offer.rate of coin_to
 | 
			
		||||
@ -1117,9 +1123,12 @@ class BasicSwap(BaseApp):
 | 
			
		||||
        except Exception:
 | 
			
		||||
            raise ValueError('Unknown coin to type')
 | 
			
		||||
 | 
			
		||||
        valid_for_seconds = extra_options.get('valid_for_seconds', 60 * 60)
 | 
			
		||||
 | 
			
		||||
        self.validateSwapType(coin_from_t, coin_to_t, swap_type)
 | 
			
		||||
        self.validateOfferAmounts(coin_from_t, coin_to_t, amount, rate, min_bid_amount)
 | 
			
		||||
        self.validateOfferLockValue(coin_from_t, coin_to_t, lock_type, lock_value)
 | 
			
		||||
        self.validateOfferValidTime(coin_from_t, coin_to_t, valid_for_seconds)
 | 
			
		||||
 | 
			
		||||
        self.mxDB.acquire()
 | 
			
		||||
        session = None
 | 
			
		||||
@ -1136,7 +1145,7 @@ class BasicSwap(BaseApp):
 | 
			
		||||
            msg_buf.rate = int(rate)
 | 
			
		||||
            msg_buf.min_bid_amount = int(min_bid_amount)
 | 
			
		||||
 | 
			
		||||
            msg_buf.time_valid = 60 * 60
 | 
			
		||||
            msg_buf.time_valid = valid_for_seconds
 | 
			
		||||
            msg_buf.lock_type = lock_type
 | 
			
		||||
            msg_buf.lock_value = lock_value
 | 
			
		||||
            msg_buf.swap_type = swap_type
 | 
			
		||||
@ -1424,7 +1433,9 @@ class BasicSwap(BaseApp):
 | 
			
		||||
        self.log.info('withdrawCoin %s %s to %s %s', value, self.getTicker(coin_type), addr_to, ' subfee' if subfee else '')
 | 
			
		||||
 | 
			
		||||
        ci = self.ci(coin_type)
 | 
			
		||||
        return ci.withdrawCoin(value, addr_to, subfee)
 | 
			
		||||
        txid = ci.withdrawCoin(value, addr_to, subfee)
 | 
			
		||||
        self.log.debug('In txn: {}'.format(txid))
 | 
			
		||||
        return txid
 | 
			
		||||
 | 
			
		||||
    def withdrawParticl(self, type_from, type_to, value, addr_to, subfee):
 | 
			
		||||
        self.log.info('withdrawParticl %s %s to %s %s %s', value, type_from, type_to, addr_to, ' subfee' if subfee else '')
 | 
			
		||||
@ -1435,7 +1446,9 @@ class BasicSwap(BaseApp):
 | 
			
		||||
            type_to = 'part'
 | 
			
		||||
 | 
			
		||||
        ci = self.ci(Coins.PART)
 | 
			
		||||
        return ci.sendTypeTo(type_from, type_to, value, addr_to, subfee)
 | 
			
		||||
        txid = ci.sendTypeTo(type_from, type_to, value, addr_to, subfee)
 | 
			
		||||
        self.log.debug('In txn: {}'.format(txid))
 | 
			
		||||
        return txid
 | 
			
		||||
 | 
			
		||||
    def cacheNewAddressForCoin(self, coin_type):
 | 
			
		||||
        self.log.debug('cacheNewAddressForCoin %s', coin_type)
 | 
			
		||||
@ -1449,7 +1462,7 @@ class BasicSwap(BaseApp):
 | 
			
		||||
        if c == Coins.PART:
 | 
			
		||||
            return True  # TODO
 | 
			
		||||
        if c == Coins.XMR:
 | 
			
		||||
            expect_address = self.getStringKV('main_wallet_addr_' + chainparams[c]['name'])
 | 
			
		||||
            expect_address = self.getStringKV('main_wallet_addr_' + ci.coin_name())
 | 
			
		||||
            if expect_address is None:
 | 
			
		||||
                self.log.warning('Can\'t find expected main wallet address for coin {}'.format(ci.coin_name()))
 | 
			
		||||
                return False
 | 
			
		||||
@ -1459,7 +1472,7 @@ class BasicSwap(BaseApp):
 | 
			
		||||
            self.log.warning('Wallet for coin {} not derived from swap seed.'.format(ci.coin_name()))
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        expect_seedid = self.getStringKV('main_wallet_seedid_' + chainparams[c]['name'])
 | 
			
		||||
        expect_seedid = self.getStringKV('main_wallet_seedid_' + ci.coin_name())
 | 
			
		||||
        if expect_seedid is None:
 | 
			
		||||
            self.log.warning('Can\'t find expected wallet seed id for coin {}'.format(ci.coin_name()))
 | 
			
		||||
            return False
 | 
			
		||||
@ -1976,7 +1989,7 @@ class BasicSwap(BaseApp):
 | 
			
		||||
            bid.initiate_txn_refund = bytes.fromhex(refund_txn)
 | 
			
		||||
 | 
			
		||||
            txid = self.submitTxn(coin_from, txn)
 | 
			
		||||
            self.log.debug('Submitted initiate txn %s to %s chain for bid %s', txid, chainparams[coin_from]['name'], bid_id.hex())
 | 
			
		||||
            self.log.debug('Submitted initiate txn %s to %s chain for bid %s', txid, ci_from.coin_name(), bid_id.hex())
 | 
			
		||||
            bid.initiate_tx = SwapTx(
 | 
			
		||||
                bid_id=bid_id,
 | 
			
		||||
                tx_type=TxTypes.ITX,
 | 
			
		||||
@ -2061,7 +2074,6 @@ class BasicSwap(BaseApp):
 | 
			
		||||
                xmr_swap.b_restore_height = wallet_restore_height
 | 
			
		||||
                self.log.warning('XMR swap restore height clamped to {}'.format(wallet_restore_height))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            for_ed25519 = True if coin_to == Coins.XMR else False
 | 
			
		||||
            kbvf = self.getPathKey(coin_from, coin_to, bid_created_at, xmr_swap.contract_count, 1, for_ed25519)
 | 
			
		||||
            kbsf = self.getPathKey(coin_from, coin_to, bid_created_at, xmr_swap.contract_count, 2, for_ed25519)
 | 
			
		||||
@ -3617,6 +3629,7 @@ class BasicSwap(BaseApp):
 | 
			
		||||
        self.validateSwapType(coin_from, coin_to, offer_data.swap_type)
 | 
			
		||||
        self.validateOfferAmounts(coin_from, coin_to, offer_data.amount_from, offer_data.rate, offer_data.min_bid_amount)
 | 
			
		||||
        self.validateOfferLockValue(coin_from, coin_to, offer_data.lock_type, offer_data.lock_value)
 | 
			
		||||
        self.validateOfferValidTime(coin_from, coin_to, offer_data.time_valid)
 | 
			
		||||
 | 
			
		||||
        assert(offer_data.time_valid >= MIN_OFFER_VALID_TIME and offer_data.time_valid <= MAX_OFFER_VALID_TIME), 'Invalid time_valid'
 | 
			
		||||
        assert(msg['sent'] + offer_data.time_valid >= now), 'Offer expired'
 | 
			
		||||
@ -3629,9 +3642,8 @@ class BasicSwap(BaseApp):
 | 
			
		||||
        elif offer_data.swap_type == SwapTypes.BUYER_FIRST:
 | 
			
		||||
            raise ValueError('TODO')
 | 
			
		||||
        elif offer_data.swap_type == SwapTypes.XMR_SWAP:
 | 
			
		||||
            assert(coin_from != Coins.XMR)
 | 
			
		||||
            assert(coin_from != Coins.PART_ANON)
 | 
			
		||||
            assert(coin_to == Coins.XMR or coin_to == Coins.PART_ANON)
 | 
			
		||||
            assert(coin_from not in (Coins.XMR, Coins.PART_ANON))
 | 
			
		||||
            assert(coin_to in (Coins.XMR, Coins.PART_ANON))
 | 
			
		||||
            self.log.debug('TODO - More restrictions')
 | 
			
		||||
        else:
 | 
			
		||||
            raise ValueError('Unknown swap type {}.'.format(offer_data.swap_type))
 | 
			
		||||
@ -4225,7 +4237,7 @@ class BasicSwap(BaseApp):
 | 
			
		||||
 | 
			
		||||
            a_lock_tx_id = ci_from.getTxHash(xmr_swap.a_lock_tx)
 | 
			
		||||
            a_lock_tx_vout = ci_from.getTxOutputPos(xmr_swap.a_lock_tx, xmr_swap.a_lock_tx_script)
 | 
			
		||||
            self.log.debug('Waiting for lock txn %s to %s chain for bid %s', a_lock_tx_id.hex(), chainparams[coin_from]['name'], bid_id.hex())
 | 
			
		||||
            self.log.debug('Waiting for lock txn %s to %s chain for bid %s', a_lock_tx_id.hex(), ci_from.coin_name(), bid_id.hex())
 | 
			
		||||
            bid.xmr_a_lock_tx = SwapTx(
 | 
			
		||||
                bid_id=bid_id,
 | 
			
		||||
                tx_type=TxTypes.XMR_SWAP_A_LOCK,
 | 
			
		||||
@ -4292,7 +4304,7 @@ class BasicSwap(BaseApp):
 | 
			
		||||
 | 
			
		||||
        vout_pos = ci_from.getTxOutputPos(xmr_swap.a_lock_tx, xmr_swap.a_lock_tx_script)
 | 
			
		||||
 | 
			
		||||
        self.log.debug('Submitted lock txn %s to %s chain for bid %s', txid_hex, chainparams[coin_from]['name'], bid_id.hex())
 | 
			
		||||
        self.log.debug('Submitted lock txn %s to %s chain for bid %s', txid_hex, ci_from.coin_name(), bid_id.hex())
 | 
			
		||||
 | 
			
		||||
        bid.xmr_a_lock_tx = SwapTx(
 | 
			
		||||
            bid_id=bid_id,
 | 
			
		||||
@ -4356,7 +4368,7 @@ class BasicSwap(BaseApp):
 | 
			
		||||
            self.logBidEvent(bid, EventLogTypes.FAILED_TX_B_LOCK_PUBLISH, str_error, session)
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        self.log.debug('Submitted lock txn %s to %s chain for bid %s', b_lock_tx_id.hex(), chainparams[coin_to]['name'], bid_id.hex())
 | 
			
		||||
        self.log.debug('Submitted lock txn %s to %s chain for bid %s', b_lock_tx_id.hex(), ci_to.coin_name(), bid_id.hex())
 | 
			
		||||
        bid.xmr_b_lock_tx = SwapTx(
 | 
			
		||||
            bid_id=bid_id,
 | 
			
		||||
            tx_type=TxTypes.XMR_SWAP_B_LOCK,
 | 
			
		||||
@ -4435,7 +4447,7 @@ class BasicSwap(BaseApp):
 | 
			
		||||
        xmr_swap.a_lock_spend_tx = ci_from.setTxSignature(xmr_swap.a_lock_spend_tx, witness_stack)
 | 
			
		||||
 | 
			
		||||
        txid = bytes.fromhex(ci_from.publishTx(xmr_swap.a_lock_spend_tx))
 | 
			
		||||
        self.log.debug('Submitted lock spend txn %s to %s chain for bid %s', txid.hex(), chainparams[coin_from]['name'], bid_id.hex())
 | 
			
		||||
        self.log.debug('Submitted lock spend txn %s to %s chain for bid %s', txid.hex(), ci_from.coin_name(), bid_id.hex())
 | 
			
		||||
        bid.xmr_a_lock_spend_tx = SwapTx(
 | 
			
		||||
            bid_id=bid_id,
 | 
			
		||||
            tx_type=TxTypes.XMR_SWAP_A_LOCK_SPEND,
 | 
			
		||||
@ -4980,7 +4992,7 @@ class BasicSwap(BaseApp):
 | 
			
		||||
        rv = {
 | 
			
		||||
            'version': self.coin_clients[coin]['core_version'],
 | 
			
		||||
            'deposit_address': self.getCachedAddressForCoin(coin),
 | 
			
		||||
            'name': chainparams[coin]['name'].capitalize(),
 | 
			
		||||
            'name': ci.coin_name().capitalize(),
 | 
			
		||||
            'blocks': blockchaininfo['blocks'],
 | 
			
		||||
            'balance': format_amount(make_int(walletinfo['balance'], scale), scale),
 | 
			
		||||
            'unconfirmed': format_amount(make_int(walletinfo.get('unconfirmed_balance'), scale), scale),
 | 
			
		||||
 | 
			
		||||
@ -37,6 +37,7 @@ chainparams = {
 | 
			
		||||
            'pubkey_address': 0x38,
 | 
			
		||||
            'script_address': 0x3c,
 | 
			
		||||
            'key_prefix': 0x6c,
 | 
			
		||||
            'stealth_key_prefix': 0x14,
 | 
			
		||||
            'hrp': 'pw',
 | 
			
		||||
            'bip44': 44,
 | 
			
		||||
            'min_amount': 1000,
 | 
			
		||||
@ -47,6 +48,7 @@ chainparams = {
 | 
			
		||||
            'pubkey_address': 0x76,
 | 
			
		||||
            'script_address': 0x7a,
 | 
			
		||||
            'key_prefix': 0x2e,
 | 
			
		||||
            'stealth_key_prefix': 0x15,
 | 
			
		||||
            'hrp': 'tpw',
 | 
			
		||||
            'bip44': 1,
 | 
			
		||||
            'min_amount': 1000,
 | 
			
		||||
@ -57,6 +59,7 @@ chainparams = {
 | 
			
		||||
            'pubkey_address': 0x76,
 | 
			
		||||
            'script_address': 0x7a,
 | 
			
		||||
            'key_prefix': 0x2e,
 | 
			
		||||
            'stealth_key_prefix': 0x15,
 | 
			
		||||
            'hrp': 'rtpw',
 | 
			
		||||
            'bip44': 1,
 | 
			
		||||
            'min_amount': 1000,
 | 
			
		||||
 | 
			
		||||
@ -33,42 +33,42 @@ G = Point(curve_secp256k1, ep.Gx, ep.Gy, ep.o)
 | 
			
		||||
SECP256K1_ORDER_HALF = ep.o // 2
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def ToDER(P):
 | 
			
		||||
def ToDER(P) -> bytes:
 | 
			
		||||
    return bytes((4, )) + int(P.x()).to_bytes(32, byteorder='big') + int(P.y()).to_bytes(32, byteorder='big')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def bytes32ToInt(b):
 | 
			
		||||
def bytes32ToInt(b) -> int:
 | 
			
		||||
    return int.from_bytes(b, byteorder='big')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def intToBytes32(i):
 | 
			
		||||
def intToBytes32(i: int) -> bytes:
 | 
			
		||||
    return i.to_bytes(32, byteorder='big')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def intToBytes32_le(i):
 | 
			
		||||
def intToBytes32_le(i: int) -> bytes:
 | 
			
		||||
    return i.to_bytes(32, byteorder='little')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def bytesToHexStr(b):
 | 
			
		||||
def bytesToHexStr(b: bytes) -> str:
 | 
			
		||||
    return codecs.encode(b, 'hex').decode('utf-8')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def hexStrToBytes(h):
 | 
			
		||||
def hexStrToBytes(h: str) -> bytes:
 | 
			
		||||
    if h.startswith('0x'):
 | 
			
		||||
        h = h[2:]
 | 
			
		||||
    return bytes.fromhex(h)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def getSecretBytes():
 | 
			
		||||
def getSecretBytes() -> bytes:
 | 
			
		||||
    i = 1 + secrets.randbelow(ep.o - 1)
 | 
			
		||||
    return intToBytes32(i)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def getSecretInt():
 | 
			
		||||
def getSecretInt() -> int:
 | 
			
		||||
    return 1 + secrets.randbelow(ep.o - 1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def getInsecureBytes():
 | 
			
		||||
def getInsecureBytes() -> bytes:
 | 
			
		||||
    while True:
 | 
			
		||||
        s = os.urandom(32)
 | 
			
		||||
 | 
			
		||||
@ -77,7 +77,7 @@ def getInsecureBytes():
 | 
			
		||||
            return s
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def getInsecureInt():
 | 
			
		||||
def getInsecureInt() -> int:
 | 
			
		||||
    while True:
 | 
			
		||||
        s = os.urandom(32)
 | 
			
		||||
 | 
			
		||||
@ -86,7 +86,7 @@ def getInsecureInt():
 | 
			
		||||
            return s_test
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def powMod(x, y, z):
 | 
			
		||||
def powMod(x, y, z) -> int:
 | 
			
		||||
    # Calculate (x ** y) % z efficiently.
 | 
			
		||||
    number = 1
 | 
			
		||||
    while y:
 | 
			
		||||
 | 
			
		||||
@ -66,11 +66,14 @@ def getCoinName(c):
 | 
			
		||||
def listAvailableCoins(swap_client):
 | 
			
		||||
    coins = []
 | 
			
		||||
    for k, v in swap_client.coin_clients.items():
 | 
			
		||||
        if k not in chainparams:
 | 
			
		||||
            continue
 | 
			
		||||
        if v['connection_type'] == 'rpc':
 | 
			
		||||
            coins.append((int(k), getCoinName(k)))
 | 
			
		||||
 | 
			
		||||
            if k == Coins.PART:
 | 
			
		||||
                coins.append((int(Coins.PART_ANON), getCoinName(k)))
 | 
			
		||||
                pass
 | 
			
		||||
                # TODO: Uncomment
 | 
			
		||||
                # coins.append((int(Coins.PART_ANON), getCoinName(k)))
 | 
			
		||||
    return coins
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -402,14 +405,17 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
			
		||||
            page_data['coin_to'] = getCoinType(get_data_entry(form_data, 'coin_to'))
 | 
			
		||||
            coin_to = Coins(page_data['coin_to'])
 | 
			
		||||
            ci_to = swap_client.ci(coin_to)
 | 
			
		||||
            if coin_to != Coins.XMR:
 | 
			
		||||
                page_data['fee_to_conf'] = ci_to._conf_target  # Set default value
 | 
			
		||||
            parsed_data['coin_to'] = coin_to
 | 
			
		||||
            if coin_to == Coins.XMR:
 | 
			
		||||
                page_data['swap_style'] = 'xmr'
 | 
			
		||||
            else:
 | 
			
		||||
                page_data['swap_style'] = 'atomic'
 | 
			
		||||
        except Exception:
 | 
			
		||||
            errors.append('Unknown Coin To')
 | 
			
		||||
 | 
			
		||||
        if parsed_data['coin_to'] in (Coins.XMR, Coins.PART_ANON):
 | 
			
		||||
            page_data['swap_style'] = 'xmr'
 | 
			
		||||
        else:
 | 
			
		||||
            page_data['swap_style'] = 'atomic'
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            page_data['amt_from'] = get_data_entry(form_data, 'amt_from')
 | 
			
		||||
            parsed_data['amt_from'] = inputAmount(page_data['amt_from'], ci_from)
 | 
			
		||||
@ -460,6 +466,12 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
			
		||||
        elif have_data_entry(form_data, 'lockseconds'):
 | 
			
		||||
            parsed_data['lock_seconds'] = int(get_data_entry(form_data, 'lockseconds'))
 | 
			
		||||
 | 
			
		||||
        if have_data_entry(form_data, 'validhrs'):
 | 
			
		||||
            page_data['validhrs'] = int(get_data_entry(form_data, 'validhrs'))
 | 
			
		||||
            parsed_data['valid_for_seconds'] = page_data['validhrs'] * 60 * 60
 | 
			
		||||
        elif have_data_entry(form_data, 'valid_for_seconds'):
 | 
			
		||||
            parsed_data['valid_for_seconds'] = int(get_data_entry(form_data, 'valid_for_seconds'))
 | 
			
		||||
 | 
			
		||||
        page_data['autoaccept'] = True if have_data_entry(form_data, 'autoaccept') else False
 | 
			
		||||
        parsed_data['autoaccept'] = page_data['autoaccept']
 | 
			
		||||
 | 
			
		||||
@ -499,7 +511,7 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
			
		||||
        swap_client = self.server.swap_client
 | 
			
		||||
 | 
			
		||||
        swap_type = SwapTypes.SELLER_FIRST
 | 
			
		||||
        if parsed_data['coin_to'] == Coins.XMR:
 | 
			
		||||
        if parsed_data['coin_to'] in (Coins.XMR, Coins.PART_ANON):
 | 
			
		||||
            swap_type = SwapTypes.XMR_SWAP
 | 
			
		||||
 | 
			
		||||
        if swap_client.coin_clients[parsed_data['coin_from']]['use_csv'] and swap_client.coin_clients[parsed_data['coin_to']]['use_csv']:
 | 
			
		||||
@ -522,6 +534,8 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
			
		||||
            extra_options['to_fee_multiplier_percent'] = parsed_data['fee_to_extra']
 | 
			
		||||
        if 'to_fee_override' in parsed_data:
 | 
			
		||||
            extra_options['to_fee_override'] = parsed_data['to_fee_override']
 | 
			
		||||
        if 'valid_for_seconds' in parsed_data:
 | 
			
		||||
            extra_options['valid_for_seconds'] = parsed_data['valid_for_seconds']
 | 
			
		||||
 | 
			
		||||
        offer_id = swap_client.postOffer(
 | 
			
		||||
            parsed_data['coin_from'],
 | 
			
		||||
@ -552,6 +566,7 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
			
		||||
            # Set defaults
 | 
			
		||||
            'fee_from_conf': 2,
 | 
			
		||||
            'fee_to_conf': 2,
 | 
			
		||||
            'validhrs': 1,
 | 
			
		||||
            'lockhrs': 32,
 | 
			
		||||
            'autoaccept': True
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -34,7 +34,7 @@ from coincurve.ecdsaotves import (
 | 
			
		||||
    ecdsaotves_rec_enc_key)
 | 
			
		||||
 | 
			
		||||
from .ecc_util import (
 | 
			
		||||
    G, ep,
 | 
			
		||||
    ep,
 | 
			
		||||
    pointToCPK, CPKToPoint,
 | 
			
		||||
    getSecretInt,
 | 
			
		||||
    b2h, i2b, b2i, i2h)
 | 
			
		||||
@ -92,23 +92,23 @@ class BTCInterface(CoinInterface):
 | 
			
		||||
        return COIN
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def exp():
 | 
			
		||||
    def exp() -> int:
 | 
			
		||||
        return 8
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def nbk():
 | 
			
		||||
    def nbk() -> int:
 | 
			
		||||
        return 32
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def nbK():  # No. of bytes requires to encode a public key
 | 
			
		||||
    def nbK() -> int:  # No. of bytes requires to encode a public key
 | 
			
		||||
        return 33
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def witnessScaleFactor():
 | 
			
		||||
    def witnessScaleFactor() -> int:
 | 
			
		||||
        return 4
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def txVersion():
 | 
			
		||||
    def txVersion() -> int:
 | 
			
		||||
        return 2
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
@ -119,11 +119,11 @@ class BTCInterface(CoinInterface):
 | 
			
		||||
        return rv
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def compareFeeRates(a, b):
 | 
			
		||||
    def compareFeeRates(a, b) -> bool:
 | 
			
		||||
        return abs(a - b) < 20
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def xmr_swap_alock_spend_tx_vsize():
 | 
			
		||||
    def xmr_swap_alock_spend_tx_vsize() -> int:
 | 
			
		||||
        return 147
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
@ -921,7 +921,7 @@ class BTCInterface(CoinInterface):
 | 
			
		||||
        rv = pubkey.verify_compact(sig, message_hash, hasher=None)
 | 
			
		||||
        assert(rv is True)
 | 
			
		||||
 | 
			
		||||
    def verifyMessage(self, address, message, signature, message_magic=None):
 | 
			
		||||
    def verifyMessage(self, address, message, signature, message_magic=None) -> bool:
 | 
			
		||||
        if message_magic is None:
 | 
			
		||||
            message_magic = chainparams[self.coin_type()]['message_magic']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -15,8 +15,9 @@ from .contrib.test_framework.script import (
 | 
			
		||||
    OP_DUP, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
from .util import encodeStealthAddress
 | 
			
		||||
from .chainparams import Coins, chainparams
 | 
			
		||||
from .interface_btc import BTCInterface
 | 
			
		||||
from .chainparams import Coins
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BalanceTypes(IntEnum):
 | 
			
		||||
@ -35,22 +36,22 @@ class PARTInterface(BTCInterface):
 | 
			
		||||
        return BalanceTypes.PLAIN
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def witnessScaleFactor():
 | 
			
		||||
    def witnessScaleFactor() -> int:
 | 
			
		||||
        return 2
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def txVersion():
 | 
			
		||||
    def txVersion() -> int:
 | 
			
		||||
        return 0xa0
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def xmr_swap_alock_spend_tx_vsize():
 | 
			
		||||
    def xmr_swap_alock_spend_tx_vsize() -> int:
 | 
			
		||||
        return 213
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def txoType():
 | 
			
		||||
        return CTxOutPart
 | 
			
		||||
 | 
			
		||||
    def setDefaults(self):
 | 
			
		||||
    def setDefaults(self) -> None:
 | 
			
		||||
        super().setDefaults()
 | 
			
		||||
        self._anon_tx_ring_size = 8  # TODO: Make option
 | 
			
		||||
 | 
			
		||||
@ -86,6 +87,11 @@ class PARTInterface(BTCInterface):
 | 
			
		||||
    def getScriptForPubkeyHash(self, pkh):
 | 
			
		||||
        return CScript([OP_DUP, OP_HASH160, pkh, OP_EQUALVERIFY, OP_CHECKSIG])
 | 
			
		||||
 | 
			
		||||
    def formatStealthAddress(self, scan_pubkey, spend_pubkey):
 | 
			
		||||
        prefix_byte = chainparams[self.coin_type()][self._network]['stealth_key_prefix']
 | 
			
		||||
 | 
			
		||||
        return encodeStealthAddress(prefix_byte, scan_pubkey, spend_pubkey)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PARTInterfaceBlind(PARTInterface):
 | 
			
		||||
    @staticmethod
 | 
			
		||||
@ -99,7 +105,17 @@ class PARTInterfaceAnon(PARTInterface):
 | 
			
		||||
        return BalanceTypes.ANON
 | 
			
		||||
 | 
			
		||||
    def publishBLockTx(self, Kbv, Kbs, output_amount, feerate):
 | 
			
		||||
        raise ValueError('TODO - new core release')
 | 
			
		||||
        sx_addr = self.formatStealthAddress(Kbv, Kbs)
 | 
			
		||||
        self._log.debug('sx_addr: {}'.format(sx_addr))
 | 
			
		||||
 | 
			
		||||
        # TODO: Fund from other balances
 | 
			
		||||
        params = ['anon', 'anon',
 | 
			
		||||
                  [{'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):
 | 
			
		||||
        raise ValueError('TODO - new core release')
 | 
			
		||||
 | 
			
		||||
@ -47,15 +47,15 @@ class XMRInterface(CoinInterface):
 | 
			
		||||
        return XMR_COIN
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def exp():
 | 
			
		||||
    def exp() -> int:
 | 
			
		||||
        return 12
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def nbk():
 | 
			
		||||
    def nbk() -> int:
 | 
			
		||||
        return 32
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def nbK():  # No. of bytes requires to encode a public key
 | 
			
		||||
    def nbK() -> int:  # No. of bytes requires to encode a public key
 | 
			
		||||
        return 32
 | 
			
		||||
 | 
			
		||||
    def __init__(self, coin_settings, network, swap_client=None):
 | 
			
		||||
 | 
			
		||||
@ -54,7 +54,8 @@
 | 
			
		||||
</select></td></tr>
 | 
			
		||||
{% endif %}
 | 
			
		||||
 | 
			
		||||
<tr class="padded_row"><td>Contract locked (hrs)</td><td><input type="number" name="lockhrs" min="1" max="64" value="{{ data.lockhrs }}" readonly></td>{% if data.swap_style != 'xmr' %}<td colspan=2>Participate txn will be locked for half the time.</td>{% endif %}</tr>
 | 
			
		||||
<tr class="padded_row"><td>Offer valid (hrs)</td><td><input type="number" name="validhrs" min="1" max="48" value="{{ data.validhrs }}" readonly></td></tr>
 | 
			
		||||
<tr><td>Contract locked (hrs)</td><td><input type="number" name="lockhrs" min="1" max="64" value="{{ data.lockhrs }}" readonly></td>{% if data.swap_style != 'xmr' %}<td colspan=2>Participate txn will be locked for half the time.</td>{% endif %}</tr>
 | 
			
		||||
<tr><td>Auto Accept Bids</td><td colspan=3><input type="checkbox" name="autoaccept_" value="aa" {% if data.autoaccept==true %} checked="true"{% endif %} disabled></td></tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -51,7 +51,8 @@
 | 
			
		||||
</select></td></tr>
 | 
			
		||||
{% endif %}
 | 
			
		||||
 | 
			
		||||
<tr class="padded_row"><td>Contract locked (hrs)</td><td><input type="number" name="lockhrs" min="1" max="96" value="{{ data.lockhrs }}"></td><td colspan=2>Participate txn will be locked for half the time.</td></tr>
 | 
			
		||||
<tr class="padded_row"><td>Offer valid (hrs)</td><td><input type="number" name="validhrs" min="1" max="48" value="{{ data.validhrs }}"></td></tr>
 | 
			
		||||
<tr><td>Contract locked (hrs)</td><td><input type="number" name="lockhrs" min="1" max="96" value="{{ data.lockhrs }}"></td>{% if data.swap_style != 'xmr' %}<td colspan=2>Participate txn will be locked for half the time.</td>{% endif %}</tr>
 | 
			
		||||
<tr><td>Auto Accept Bids</td><td colspan=3><input type="checkbox" name="autoaccept" value="aa" {% if data.autoaccept==true %} checked="true"{% endif %}></td></tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -27,7 +27,7 @@ def assert_cond(v, err='Bad opcode'):
 | 
			
		||||
        raise ValueError(err)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def toBool(s):
 | 
			
		||||
def toBool(s) -> bool:
 | 
			
		||||
    return s.lower() in ["1", "true"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -170,7 +170,7 @@ def SerialiseNum(n):
 | 
			
		||||
    return bytes((len(rv),)) + rv
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def DeserialiseNum(b, o=0):
 | 
			
		||||
def DeserialiseNum(b, o=0) -> int:
 | 
			
		||||
    if b[o] == 0:
 | 
			
		||||
        return 0
 | 
			
		||||
    if b[o] > 0x50 and b[o] <= 0x50 + 16:
 | 
			
		||||
@ -276,7 +276,7 @@ def make_int(v, scale=8, r=0):  # r = 0, no rounding, fail, r > 0 round up, r <
 | 
			
		||||
    return rv
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def validate_amount(amount, scale=8):
 | 
			
		||||
def validate_amount(amount, scale=8) -> bool:
 | 
			
		||||
    str_amount = float_to_str(amount) if type(amount) == float else str(amount)
 | 
			
		||||
    has_decimal = False
 | 
			
		||||
    for c in str_amount:
 | 
			
		||||
@ -324,3 +324,16 @@ def getP2SHScriptForHash(p2sh):
 | 
			
		||||
 | 
			
		||||
def getP2WSH(script):
 | 
			
		||||
    return bytes((OpCodes.OP_0, 0x20)) + hashlib.sha256(script).digest()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def encodeStealthAddress(prefix_byte, scan_pubkey, spend_pubkey):
 | 
			
		||||
    data = bytes((0x00,))
 | 
			
		||||
    data += scan_pubkey
 | 
			
		||||
    data += bytes((0x01,))
 | 
			
		||||
    data += spend_pubkey
 | 
			
		||||
    data += bytes((0x00,))  # number_signatures - unused
 | 
			
		||||
    data += bytes((0x00,))  # num prefix bits
 | 
			
		||||
 | 
			
		||||
    b = bytes((prefix_byte,)) + data
 | 
			
		||||
    b += hashlib.sha256(hashlib.sha256(b).digest()).digest()[:4]
 | 
			
		||||
    return b58encode(b)
 | 
			
		||||
 | 
			
		||||
@ -235,6 +235,7 @@ def wait_for_balance(delay_event, url, balance_key, expect_amount, iterations=20
 | 
			
		||||
    i = 0
 | 
			
		||||
    while not delay_event.is_set():
 | 
			
		||||
        rv_js = json.loads(urlopen(url).read())
 | 
			
		||||
        print("[rm] rv_js", rv_js)
 | 
			
		||||
        if float(rv_js[balance_key]) >= expect_amount:
 | 
			
		||||
            break
 | 
			
		||||
        delay_event.wait(delay_time)
 | 
			
		||||
 | 
			
		||||
@ -703,9 +703,10 @@ class Test(unittest.TestCase):
 | 
			
		||||
        js_1 = json.loads(urlopen('http://127.0.0.1:1801/json/wallets/part').read())
 | 
			
		||||
        assert(float(js_1['balance']) > 200.0)
 | 
			
		||||
 | 
			
		||||
        callnoderpc(1, 'reservebalance', [True, 1000000])  # Stop staking to avoid conflicts (input used by tx->anon staked before tx gets in the chain)
 | 
			
		||||
        post_json = {
 | 
			
		||||
            'value': 100,
 | 
			
		||||
            'address': js_0['stealth_address'],
 | 
			
		||||
            'address': js_1['stealth_address'],
 | 
			
		||||
            'subfee': False,
 | 
			
		||||
            'type_to': 'anon',
 | 
			
		||||
        }
 | 
			
		||||
@ -718,8 +719,13 @@ class Test(unittest.TestCase):
 | 
			
		||||
            assert(len(json_rv['txid']) == 64)
 | 
			
		||||
 | 
			
		||||
        logging.info('Waiting for anon balance')
 | 
			
		||||
        wait_for_balance(test_delay_event, 'http://127.0.0.1:1800/json/wallets/part', 'anon_balance', 110.0)
 | 
			
		||||
        try:
 | 
			
		||||
            wait_for_balance(test_delay_event, 'http://127.0.0.1:1801/json/wallets/part', 'anon_balance', 110.0)
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            ft = callnoderpc(0, 'filtertransactions', [{'count': 0}])
 | 
			
		||||
            raise e
 | 
			
		||||
 | 
			
		||||
        callnoderpc(1, 'reservebalance', [False])
 | 
			
		||||
        post_json = {
 | 
			
		||||
            'value': 10,
 | 
			
		||||
            'address': js_0['stealth_address'],
 | 
			
		||||
@ -727,7 +733,7 @@ class Test(unittest.TestCase):
 | 
			
		||||
            'type_from': 'anon',
 | 
			
		||||
            'type_to': 'blind',
 | 
			
		||||
        }
 | 
			
		||||
        json_rv = json.loads(post_json_req('http://127.0.0.1:1800/json/wallets/part/withdraw', post_json))
 | 
			
		||||
        json_rv = json.loads(post_json_req('http://127.0.0.1:1801/json/wallets/part/withdraw', post_json))
 | 
			
		||||
        assert(len(json_rv['txid']) == 64)
 | 
			
		||||
 | 
			
		||||
        logging.info('Waiting for blind balance')
 | 
			
		||||
@ -735,14 +741,13 @@ class Test(unittest.TestCase):
 | 
			
		||||
        if float(js_0['blind_balance']) >= 10.0:
 | 
			
		||||
            raise ValueError('Expect blind balance < 10')
 | 
			
		||||
 | 
			
		||||
        logging.warning('TODO')
 | 
			
		||||
        return
 | 
			
		||||
        return  # TODO
 | 
			
		||||
 | 
			
		||||
        amt_swap = make_int(random.uniform(0.1, 2.0), scale=8, r=1)
 | 
			
		||||
        rate_swap = make_int(random.uniform(2.0, 20.0), scale=8, r=1)
 | 
			
		||||
        offer_id = swap_clients[0].postOffer(Coins.BTC, Coins.PART_ANON, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP)
 | 
			
		||||
        wait_for_offer(test_delay_event, swap_clients[1], offer_id)
 | 
			
		||||
        offers = swap_clients[1].listOffers(filters={'offer_id': offer_id})
 | 
			
		||||
        offers = swap_clients[0].listOffers(filters={'offer_id': offer_id})
 | 
			
		||||
        offer = offers[0]
 | 
			
		||||
 | 
			
		||||
        bid_id = swap_clients[1].postXmrBid(offer_id, offer.amount_from)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user