Check for duplicate pubkeys.
Add test for 'non-BIP68-final'.
This commit is contained in:
		
							parent
							
								
									4bde19fe33
								
							
						
					
					
						commit
						645571e47c
					
				@ -36,7 +36,6 @@ from .util import (
 | 
			
		||||
    format_amount,
 | 
			
		||||
    encodeAddress,
 | 
			
		||||
    decodeAddress,
 | 
			
		||||
    SerialiseNum,
 | 
			
		||||
    DeserialiseNum,
 | 
			
		||||
    decodeWif,
 | 
			
		||||
    toWIF,
 | 
			
		||||
@ -80,10 +79,14 @@ from .db import (
 | 
			
		||||
    XmrSwap,
 | 
			
		||||
    XmrSplitData,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
from .explorers import ExplorerInsight, ExplorerBitAps, ExplorerChainz
 | 
			
		||||
import basicswap.config as cfg
 | 
			
		||||
from .base import BaseApp
 | 
			
		||||
from .explorers import (
 | 
			
		||||
    ExplorerInsight,
 | 
			
		||||
    ExplorerBitAps,
 | 
			
		||||
    ExplorerChainz,
 | 
			
		||||
)
 | 
			
		||||
import basicswap.config as cfg
 | 
			
		||||
import basicswap.protocols.atomic_swap_1 as atomic_swap_1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
MIN_OFFER_VALID_TIME = 60 * 10
 | 
			
		||||
@ -348,37 +351,6 @@ def decodeSequence(lock_value):
 | 
			
		||||
    return lock_value & SEQUENCE_LOCKTIME_MASK
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def buildContractScript(lock_val, secret_hash, pkh_redeem, pkh_refund, op_lock=OpCodes.OP_CHECKSEQUENCEVERIFY):
 | 
			
		||||
    script = bytearray([
 | 
			
		||||
        OpCodes.OP_IF,
 | 
			
		||||
        OpCodes.OP_SIZE,
 | 
			
		||||
        0x01, 0x20,  # 32
 | 
			
		||||
        OpCodes.OP_EQUALVERIFY,
 | 
			
		||||
        OpCodes.OP_SHA256,
 | 
			
		||||
        0x20]) \
 | 
			
		||||
        + secret_hash \
 | 
			
		||||
        + bytearray([
 | 
			
		||||
            OpCodes.OP_EQUALVERIFY,
 | 
			
		||||
            OpCodes.OP_DUP,
 | 
			
		||||
            OpCodes.OP_HASH160,
 | 
			
		||||
            0x14]) \
 | 
			
		||||
        + pkh_redeem \
 | 
			
		||||
        + bytearray([OpCodes.OP_ELSE, ]) \
 | 
			
		||||
        + SerialiseNum(lock_val) \
 | 
			
		||||
        + bytearray([
 | 
			
		||||
            op_lock,
 | 
			
		||||
            OpCodes.OP_DROP,
 | 
			
		||||
            OpCodes.OP_DUP,
 | 
			
		||||
            OpCodes.OP_HASH160,
 | 
			
		||||
            0x14]) \
 | 
			
		||||
        + pkh_refund \
 | 
			
		||||
        + bytearray([
 | 
			
		||||
            OpCodes.OP_ENDIF,
 | 
			
		||||
            OpCodes.OP_EQUALVERIFY,
 | 
			
		||||
            OpCodes.OP_CHECKSIG])
 | 
			
		||||
    return script
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def extractScriptSecretHash(script):
 | 
			
		||||
    return script[7:39]
 | 
			
		||||
 | 
			
		||||
@ -748,7 +720,7 @@ class BasicSwap(BaseApp):
 | 
			
		||||
                self.db_version = db_version
 | 
			
		||||
                kv = session.query(DBKVInt).filter_by(key='db_version').first()
 | 
			
		||||
                if not kv:
 | 
			
		||||
                    kv = DBKVInt(key=str_key, value=db_version)
 | 
			
		||||
                    kv = DBKVInt(key='db_version', value=db_version)
 | 
			
		||||
                else:
 | 
			
		||||
                    kv.value = db_version
 | 
			
		||||
                session.add(kv)
 | 
			
		||||
@ -1658,14 +1630,14 @@ class BasicSwap(BaseApp):
 | 
			
		||||
        else:
 | 
			
		||||
            if offer.lock_type < ABS_LOCK_BLOCKS:
 | 
			
		||||
                sequence = getExpectedSequence(offer.lock_type, offer.lock_value, coin_from)
 | 
			
		||||
                script = buildContractScript(sequence, secret_hash, bid.pkhash_buyer, pkhash_refund)
 | 
			
		||||
                script = atomic_swap_1.buildContractScript(sequence, secret_hash, bid.pkhash_buyer, pkhash_refund)
 | 
			
		||||
            else:
 | 
			
		||||
                if offer.lock_type == ABS_LOCK_BLOCKS:
 | 
			
		||||
                    lock_value = self.callcoinrpc(coin_from, 'getblockchaininfo')['blocks'] + offer.lock_value
 | 
			
		||||
                else:
 | 
			
		||||
                    lock_value = int(time.time()) + offer.lock_value
 | 
			
		||||
                self.log.debug('Initiate %s lock_value %d %d', coin_from, offer.lock_value, lock_value)
 | 
			
		||||
                script = buildContractScript(lock_value, secret_hash, bid.pkhash_buyer, pkhash_refund, OpCodes.OP_CHECKLOCKTIMEVERIFY)
 | 
			
		||||
                script = atomic_swap_1.buildContractScript(lock_value, secret_hash, bid.pkhash_buyer, pkhash_refund, OpCodes.OP_CHECKLOCKTIMEVERIFY)
 | 
			
		||||
 | 
			
		||||
            p2sh = self.callcoinrpc(Coins.PART, 'decodescript', [script.hex()])['p2sh']
 | 
			
		||||
 | 
			
		||||
@ -2061,7 +2033,7 @@ class BasicSwap(BaseApp):
 | 
			
		||||
        lock_value = offer.lock_value // 2
 | 
			
		||||
        if offer.lock_type < ABS_LOCK_BLOCKS:
 | 
			
		||||
            sequence = getExpectedSequence(offer.lock_type, lock_value, coin_to)
 | 
			
		||||
            participate_script = buildContractScript(sequence, secret_hash, pkhash_seller, pkhash_buyer_refund)
 | 
			
		||||
            participate_script = atomic_swap_1.buildContractScript(sequence, secret_hash, pkhash_seller, pkhash_buyer_refund)
 | 
			
		||||
        else:
 | 
			
		||||
            # Lock from the height or time of the block containing the initiate txn
 | 
			
		||||
            coin_from = Coins(offer.coin_from)
 | 
			
		||||
@ -2092,7 +2064,7 @@ class BasicSwap(BaseApp):
 | 
			
		||||
                self.log.debug('Setting lock value from time of block %s %s', coin_from, initiate_tx_block_hash)
 | 
			
		||||
                contract_lock_value = initiate_tx_block_time + lock_value
 | 
			
		||||
            self.log.debug('participate %s lock_value %d %d', coin_to, lock_value, contract_lock_value)
 | 
			
		||||
            participate_script = buildContractScript(contract_lock_value, secret_hash, pkhash_seller, pkhash_buyer_refund, OpCodes.OP_CHECKLOCKTIMEVERIFY)
 | 
			
		||||
            participate_script = atomic_swap_1.buildContractScript(contract_lock_value, secret_hash, pkhash_seller, pkhash_buyer_refund, OpCodes.OP_CHECKLOCKTIMEVERIFY)
 | 
			
		||||
        return participate_script
 | 
			
		||||
 | 
			
		||||
    def createParticipateTxn(self, bid_id, bid, offer, participate_script):
 | 
			
		||||
@ -3630,6 +3602,15 @@ class BasicSwap(BaseApp):
 | 
			
		||||
        if not ci_from.verifyPubkey(xmr_swap.pkarl):
 | 
			
		||||
            raise ValueError('Invalid pubkey.')
 | 
			
		||||
 | 
			
		||||
        if xmr_swap.pkbvl == xmr_swap.pkbvf:
 | 
			
		||||
            raise ValueError('Duplicate scriptless view pubkey.')
 | 
			
		||||
        if xmr_swap.pkbsl == xmr_swap.pkbsf:
 | 
			
		||||
            raise ValueError('Duplicate scriptless spend pubkey.')
 | 
			
		||||
        if xmr_swap.pkal == xmr_swap.pkaf:
 | 
			
		||||
            raise ValueError('Duplicate script spend pubkey.')
 | 
			
		||||
        if xmr_swap.pkarl == xmr_swap.pkarf:
 | 
			
		||||
            raise ValueError('Duplicate script spend pubkey.')
 | 
			
		||||
 | 
			
		||||
        bid.setState(BidStates.SWAP_DELAYING)
 | 
			
		||||
        self.saveBidInSession(bid.bid_id, bid, session, xmr_swap)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -19,13 +19,14 @@ class ECCParameters():
 | 
			
		||||
        self.o = o
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ep = ECCParameters( \
 | 
			
		||||
    p  = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f, \
 | 
			
		||||
    a  = 0x0, \
 | 
			
		||||
    b  = 0x7, \
 | 
			
		||||
    Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798, \
 | 
			
		||||
    Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8, \
 | 
			
		||||
    o  = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141)  # noqa: E221,E251,E502
 | 
			
		||||
ep = ECCParameters(
 | 
			
		||||
    p=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,
 | 
			
		||||
    a=0x0,
 | 
			
		||||
    b=0x7,
 | 
			
		||||
    Gx=0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,
 | 
			
		||||
    Gy=0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8,
 | 
			
		||||
    o=0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
curve_secp256k1 = CurveFp(ep.p, ep.a, ep.b)
 | 
			
		||||
G = Point(curve_secp256k1, ep.Gx, ep.Gy, ep.o)
 | 
			
		||||
 | 
			
		||||
@ -670,7 +670,7 @@ class BTCInterface(CoinInterface):
 | 
			
		||||
        assert_cond(tx.vin[0].prevout.hash == b2i(lock_tx_id) and tx.vin[0].prevout.n == locked_n, 'Input prevout mismatch')
 | 
			
		||||
 | 
			
		||||
        assert_cond(len(tx.vout) == 1, 'tx doesn\'t have one output')
 | 
			
		||||
        p2wpkh =  self.getScriptForPubkeyHash(a_pkhash_f)
 | 
			
		||||
        p2wpkh = self.getScriptForPubkeyHash(a_pkhash_f)
 | 
			
		||||
        assert_cond(tx.vout[0].scriptPubKey == p2wpkh, 'Bad output destination')
 | 
			
		||||
 | 
			
		||||
        fee_paid = locked_coin - tx.vout[0].nValue
 | 
			
		||||
 | 
			
		||||
@ -159,6 +159,8 @@ class XMRInterface(CoinInterface):
 | 
			
		||||
        return(i < edf.l and i > 8)
 | 
			
		||||
 | 
			
		||||
    def verifyPubkey(self, pubkey_bytes):
 | 
			
		||||
        # Calls ed25519_decode_check_point() in secp256k1
 | 
			
		||||
        # Checks for small order
 | 
			
		||||
        return verify_ed25519_point(pubkey_bytes)
 | 
			
		||||
 | 
			
		||||
    def proveDLEAG(self, key):
 | 
			
		||||
@ -240,13 +242,13 @@ class XMRInterface(CoinInterface):
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            logging.info('rpc_cb failed %s', str(e))
 | 
			
		||||
            current_height = None  # If the transfer is available it will be deep enough
 | 
			
		||||
            #   and (current_height is None or current_height - transfer['block_height'] > cb_block_confirmed):
 | 
			
		||||
        '''
 | 
			
		||||
        params = {'transfer_type': 'available'}
 | 
			
		||||
        rv = self.rpc_wallet_cb('incoming_transfers', params)
 | 
			
		||||
        if 'transfers' in rv:
 | 
			
		||||
            for transfer in rv['transfers']:
 | 
			
		||||
                if transfer['amount'] == cb_swap_value:
 | 
			
		||||
                #   and (current_height is None or current_height - transfer['block_height'] > cb_block_confirmed):
 | 
			
		||||
                    return {'txid': transfer['tx_hash'], 'amount': transfer['amount'], 'height': 0 if 'block_height' not in transfer else transfer['block_height']}
 | 
			
		||||
                else:
 | 
			
		||||
                    logging.warning('Incorrect amount detected for coin b lock txn: {}'.format(transfer['tx_hash']))
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										0
									
								
								basicswap/protocols/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								basicswap/protocols/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										43
									
								
								basicswap/protocols/atomic_swap_1.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								basicswap/protocols/atomic_swap_1.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,43 @@
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2020 tecnovert
 | 
			
		||||
# Distributed under the MIT software license, see the accompanying
 | 
			
		||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
 | 
			
		||||
 | 
			
		||||
from basicswap.util import (
 | 
			
		||||
    SerialiseNum,
 | 
			
		||||
)
 | 
			
		||||
from basicswap.script import (
 | 
			
		||||
    OpCodes,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def buildContractScript(lock_val, secret_hash, pkh_redeem, pkh_refund, op_lock=OpCodes.OP_CHECKSEQUENCEVERIFY):
 | 
			
		||||
    script = bytearray([
 | 
			
		||||
        OpCodes.OP_IF,
 | 
			
		||||
        OpCodes.OP_SIZE,
 | 
			
		||||
        0x01, 0x20,  # 32
 | 
			
		||||
        OpCodes.OP_EQUALVERIFY,
 | 
			
		||||
        OpCodes.OP_SHA256,
 | 
			
		||||
        0x20]) \
 | 
			
		||||
        + secret_hash \
 | 
			
		||||
        + bytearray([
 | 
			
		||||
            OpCodes.OP_EQUALVERIFY,
 | 
			
		||||
            OpCodes.OP_DUP,
 | 
			
		||||
            OpCodes.OP_HASH160,
 | 
			
		||||
            0x14]) \
 | 
			
		||||
        + pkh_redeem \
 | 
			
		||||
        + bytearray([OpCodes.OP_ELSE, ]) \
 | 
			
		||||
        + SerialiseNum(lock_val) \
 | 
			
		||||
        + bytearray([
 | 
			
		||||
            op_lock,
 | 
			
		||||
            OpCodes.OP_DROP,
 | 
			
		||||
            OpCodes.OP_DUP,
 | 
			
		||||
            OpCodes.OP_HASH160,
 | 
			
		||||
            0x14]) \
 | 
			
		||||
        + pkh_refund \
 | 
			
		||||
        + bytearray([
 | 
			
		||||
            OpCodes.OP_ENDIF,
 | 
			
		||||
            OpCodes.OP_EQUALVERIFY,
 | 
			
		||||
            OpCodes.OP_CHECKSIG])
 | 
			
		||||
    return script
 | 
			
		||||
							
								
								
									
										5
									
								
								basicswap/protocols/xmr_swap_1.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								basicswap/protocols/xmr_swap_1.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2020 tecnovert
 | 
			
		||||
# Distributed under the MIT software license, see the accompanying
 | 
			
		||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
 | 
			
		||||
@ -760,6 +760,36 @@ class Test(unittest.TestCase):
 | 
			
		||||
        self.wait_for_bid(swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=180)
 | 
			
		||||
        self.wait_for_bid(swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True)
 | 
			
		||||
 | 
			
		||||
    def test_10_locked_refundtx(self):
 | 
			
		||||
        logging.info('---------- Test Refund tx is locked')
 | 
			
		||||
        swap_clients = self.swap_clients
 | 
			
		||||
        offer_id = swap_clients[0].postOffer(Coins.BTC, Coins.XMR, 10 * COIN, 100 * XMR_COIN, 10 * COIN, SwapTypes.XMR_SWAP)
 | 
			
		||||
        self.wait_for_offer(swap_clients[1], offer_id)
 | 
			
		||||
        offers = swap_clients[1].listOffers(filters={'offer_id': offer_id})
 | 
			
		||||
        offer = offers[0]
 | 
			
		||||
 | 
			
		||||
        bid_id = swap_clients[1].postXmrBid(offer_id, offer.amount_from)
 | 
			
		||||
 | 
			
		||||
        self.wait_for_bid(swap_clients[0], bid_id, BidStates.BID_RECEIVED)
 | 
			
		||||
 | 
			
		||||
        bid, xmr_swap = swap_clients[0].getXmrBid(bid_id)
 | 
			
		||||
        assert(xmr_swap)
 | 
			
		||||
 | 
			
		||||
        swap_clients[1].setBidDebugInd(bid_id, DebugTypes.BID_STOP_AFTER_COIN_A_LOCK)
 | 
			
		||||
 | 
			
		||||
        swap_clients[0].acceptXmrBid(bid_id)
 | 
			
		||||
 | 
			
		||||
        self.wait_for_bid(swap_clients[0], bid_id, BidStates.XMR_SWAP_SCRIPT_COIN_LOCKED, wait_for=180)
 | 
			
		||||
 | 
			
		||||
        bid, xmr_swap = swap_clients[0].getXmrBid(bid_id)
 | 
			
		||||
        assert(xmr_swap)
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            swap_clients[0].ci(Coins.BTC).publishTx(xmr_swap.a_lock_refund_tx)
 | 
			
		||||
            assert(False), 'Lock refund tx should be locked'
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            assert('non-BIP68-final' in str(e))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    unittest.main()
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user