示例#1
0
    def test_makeInt12(self):
        def test_case(vs, vf, expect_int):
            i = make_int(vs, 12)
            assert (i == expect_int and isinstance(i, int))
            i = make_int(vf, 12)
            assert (i == expect_int and isinstance(i, int))
            vs_out = format_amount(i, 12)
            # Strip
            for i in range(7):
                if vs_out[-1] == '0':
                    vs_out = vs_out[:-1]
            if '.' in vs:
                assert (vs_out == vs)
            else:
                assert (vs_out[:-2] == vs)

        test_case('0.123456789', 0.123456789, 123456789000)
        test_case('0.123456789123', 0.123456789123, 123456789123)
        try:
            make_int('0.1234567891234', 12)
            assert (False)
        except Exception as e:
            assert (str(e) == 'Mantissa too long')
        validate_amount('0.123456789123', 12)
        try:
            validate_amount('0.1234567891234', 12)
            assert (False)
        except Exception as e:
            assert ('Too many decimal places' in str(e))
        try:
            validate_amount(0.1234567891234, 12)
            assert (False)
        except Exception as e:
            assert ('Too many decimal places' in str(e))
示例#2
0
 def test_case(vs, vf, expect_int):
     i = make_int(vs, 12)
     assert (i == expect_int and isinstance(i, int))
     i = make_int(vf, 12)
     assert (i == expect_int and isinstance(i, int))
     vs_out = format_amount(i, 12)
     # Strip
     for i in range(7):
         if vs_out[-1] == '0':
             vs_out = vs_out[:-1]
     if '.' in vs:
         assert (vs_out == vs)
     else:
         assert (vs_out[:-2] == vs)
示例#3
0
    def test_make_int(self):
        def test_case(vs, vf, expect_int):
            i = make_int(vs)
            assert (i == expect_int and isinstance(i, int))
            i = make_int(vf)
            assert (i == expect_int and isinstance(i, int))
            vs_out = format_amount(i, 8)
            # Strip
            for i in range(7):
                if vs_out[-1] == '0':
                    vs_out = vs_out[:-1]
            if '.' in vs:
                assert (vs_out == vs)
            else:
                assert (vs_out[:-2] == vs)

        test_case('0', 0, 0)
        test_case('1', 1, 100000000)
        test_case('10', 10, 1000000000)
        test_case('0.00899999', 0.00899999, 899999)
        test_case('899999.0', 899999.0, 89999900000000)
        test_case('899999.00899999', 899999.00899999, 89999900899999)
        test_case('0.0', 0.0, 0)
        test_case('1.0', 1.0, 100000000)
        test_case('1.1', 1.1, 110000000)
        test_case('1.2', 1.2, 120000000)
        test_case('0.00899991', 0.00899991, 899991)
        test_case('0.0089999', 0.0089999, 899990)
        test_case('0.0089991', 0.0089991, 899910)
        test_case('0.123', 0.123, 12300000)
        test_case('123000.000123', 123000.000123, 12300000012300)

        try:
            make_int('0.123456789')
            assert (False)
        except Exception as e:
            assert (str(e) == 'Mantissa too long')
        validate_amount('0.12345678')

        # floor
        assert (make_int('0.123456789', r=-1) == 12345678)
        # Round up
        assert (make_int('0.123456789', r=1) == 12345679)
示例#4
0
    def test_04_follower_recover_b_lock_tx(self):
        ID_ALICE_SWAP = os.path.join(TEST_DIR,
                                     'test_04_alice_swap_state') + '.json'
        ID_BOB_SWAP = os.path.join(TEST_DIR,
                                   'test_04_bob_swap_state') + '.json'

        alice_btc_start = make_int(
            callnoderpc(ID_ALICE_PART, 'getbalances')['mine']['trusted'])
        bob_btc_start = make_int(
            callnoderpc(ID_BOB_PART, 'getbalances')['mine']['trusted'])
        alice_xmr_start = self.callxmrnodewallet(ID_ALICE_XMR,
                                                 'get_balance')['balance']
        bob_xmr_start = self.callxmrnodewallet(ID_BOB_XMR,
                                               'get_balance')['balance']

        logging.info(
            'Test start wallet states:\nalice_btc_start: %ld\nbob_btc_start: %ld\nalice_xmr_start: %ld\nbob_xmr_start: %ld',
            alice_btc_start, bob_btc_start, alice_xmr_start, bob_xmr_start)

        # Same steps as in test_01_swap_successful
        self.startSwap(ID_ALICE_SWAP, ID_BOB_SWAP, 3, 4)
        msg2f = callSwapTool(ID_ALICE_SWAP, 'msg2f')
        callSwapTool(ID_BOB_SWAP, 'processmsg', str_param=msg2f)
        msg3l = callSwapTool(ID_BOB_SWAP, 'msg3l')
        callSwapTool(ID_ALICE_SWAP, 'processmsg', str_param=msg3l)
        msg4f = callSwapTool(ID_ALICE_SWAP, 'msg4f')
        a_lock_txid = callSwapTool(ID_ALICE_SWAP, 'publishalocktx').strip()

        logging.info(
            'Bob verifies the lock spend tx and encrypted signature from Alice.'
        )
        callSwapTool(ID_BOB_SWAP, 'processmsg', str_param=msg4f)

        logging.info('Bob waits for the script-chain lock tx to confirm.')

        num_tries = 30
        for i in range(1 + num_tries):
            rv = callSwapTool(ID_BOB_SWAP, 'confirmalocktx')
            print('confirmalocktx', rv)
            if rv.strip() == 'True':
                break

            if i >= num_tries:
                raise ValueError(
                    'Timed out waiting for script-chain lock tx to confirm.')

        logging.info('Then publishes the second-chain lock tx.')
        b_lock_txid = callSwapTool(ID_BOB_SWAP, 'publishblocktx')

        logging.info(
            'Alice waits for the scriptless-chain lock tx to confirm.')

        num_tries = 120
        for i in range(1 + num_tries):
            rv = callSwapTool(ID_ALICE_SWAP, 'confirmblocktx')
            print('confirmblocktx', rv)
            if rv.strip() == 'True':
                break

            if i >= num_tries:
                raise ValueError(
                    'Timed out waiting for scriptless-chain lock tx to confirm.'
                )
            time.sleep(2)

        logging.info(
            'Alice detects a problem with the scriptless-chain lock tx and decides to cancel the swap'
        )

        a_lock_refund_txid = self.publishALockRefundTx(ID_ALICE_PART,
                                                       ID_ALICE_SWAP)

        # Import key to receive refund in wallet.  Simple method for testing.
        kal = callSwapTool(ID_ALICE_SWAP, 'getkal')
        kal_wif = bytes_to_wif(h2b(kal), prefix=0x2e)
        callnoderpc(ID_ALICE_PART, 'importprivkey', [kal_wif, 'swap refund'])

        alockrefundspendtxid = callSwapTool(ID_ALICE_SWAP,
                                            'publishalockrefundspendtx')

        rv = callnoderpc(ID_ALICE_PART, 'getbalances')
        print('getbalances', dumpj(rv))
        alice_btc = make_int(rv['mine']['trusted']) + make_int(
            rv['mine']['untrusted_pending'])
        logging.info('alice_btc %ld', alice_btc)

        logging.info('Bob waits for Alice to spend the lock refund tx.')

        num_tries = 20
        for i in range(1 + num_tries):
            rv = callSwapTool(ID_BOB_SWAP, 'findalockrefundspendtx')
            print('findalockrefundspendtx', rv)
            if rv.strip() == 'True':
                break
            if i >= num_tries:
                raise ValueError(
                    'Timed out waiting for script-chain lock refund spend tx to confirm.'
                )
            time.sleep(1)

        logging.info('Then he can recover his scriptless-chain lock tx coin.')

        self.callxmrnodewallet(ID_BOB_XMR, 'open_wallet',
                               {'filename': 'testwallet'})
        xmr_addr_bob = self.callxmrnodewallet(ID_BOB_XMR,
                                              'get_address')['address']

        rv = callSwapTool(ID_BOB_SWAP, 'redeemblocktx', str_param=xmr_addr_bob)
        print('redeemblocktx', rv)

        self.callxmrnodewallet(ID_BOB_XMR, 'close_wallet')
        self.callxmrnodewallet(ID_BOB_XMR, 'open_wallet',
                               {'filename': 'testwallet'})
示例#5
0
    def test_03_follower_recover_a_lock_tx(self):
        ID_ALICE_SWAP = os.path.join(TEST_DIR,
                                     'test_03_alice_swap_state') + '.json'
        ID_BOB_SWAP = os.path.join(TEST_DIR,
                                   'test_03_bob_swap_state') + '.json'

        alice_btc_start = make_int(
            callnoderpc(ID_ALICE_PART, 'getbalances')['mine']['trusted'])
        bob_btc_start = make_int(
            callnoderpc(ID_BOB_PART, 'getbalances')['mine']['trusted'])
        alice_xmr_start = self.callxmrnodewallet(ID_ALICE_XMR,
                                                 'get_balance')['balance']
        bob_xmr_start = self.callxmrnodewallet(ID_BOB_XMR,
                                               'get_balance')['balance']

        logging.info(
            'Test start wallet states:\nalice_btc_start: %ld\nbob_btc_start: %ld\nalice_xmr_start: %ld\nbob_xmr_start: %ld',
            alice_btc_start, bob_btc_start, alice_xmr_start, bob_xmr_start)

        # Same steps as in test_01_swap_successful
        self.startSwap(ID_ALICE_SWAP, ID_BOB_SWAP, 3, 4)
        msg2f = callSwapTool(ID_ALICE_SWAP, 'msg2f')
        callSwapTool(ID_BOB_SWAP, 'processmsg', str_param=msg2f)
        msg3l = callSwapTool(ID_BOB_SWAP, 'msg3l')
        callSwapTool(ID_ALICE_SWAP, 'processmsg', str_param=msg3l)
        msg4f = callSwapTool(ID_ALICE_SWAP, 'msg4f')
        a_lock_txid = callSwapTool(ID_ALICE_SWAP, 'publishalocktx').strip()

        logging.info('Alice stops responding here.')

        # Wait for the mining node to receive the tx
        for i in range(10):
            try:
                callnoderpc(0, 'getrawtransaction', [a_lock_txid])
                break
            except Exception as e:
                print('Waiting for node 0 to see tx', str(e))
            time.sleep(1)

        a_lock_refund_txid = self.publishALockRefundTx(ID_BOB_PART,
                                                       ID_BOB_SWAP)

        # Wait for the mining node to receive the tx
        for i in range(10):
            try:
                callnoderpc(0, 'getrawtransaction', [a_lock_refund_txid])
                break
            except Exception as e:
                print('Waiting for node 0 to see tx', str(e))
            time.sleep(1)

        btc_addr_bob = callnoderpc(
            ID_BOB_PART, 'getnewaddress',
            ['bob\'s addr', False, False, False, 'bech32'])
        ignr, a_pkhash_f = segwit_addr.decode('rtpw', btc_addr_bob)
        assert (a_pkhash_f is not None)

        a_lock_refund_spend_txid = self.publishALockRefundFollowerSpendTx(
            ID_BOB_PART, ID_BOB_SWAP, a_pkhash_f)

        rv = callnoderpc(ID_BOB_PART, 'getbalances')
        print('getbalances', dumpj(rv))
        bob_btc_end = make_int(rv['mine']['trusted']) + make_int(
            rv['mine']['untrusted_pending'])
        logging.info('bob_btc_end %ld', bob_btc_end)

        assert (bob_btc_end > bob_btc_start)
示例#6
0
    def test_02_leader_recover_a_lock_tx(self):
        ID_ALICE_SWAP = os.path.join(TEST_DIR,
                                     'test_02_alice_swap_state') + '.json'
        ID_BOB_SWAP = os.path.join(TEST_DIR,
                                   'test_02_bob_swap_state') + '.json'

        alice_btc_start = make_int(
            callnoderpc(ID_ALICE_PART, 'getbalances')['mine']['trusted'])
        bob_btc_start = make_int(
            callnoderpc(ID_BOB_PART, 'getbalances')['mine']['trusted'])

        alice_xmr_start = self.callxmrnodewallet(ID_ALICE_XMR,
                                                 'get_balance')['balance']
        bob_xmr_start = self.callxmrnodewallet(ID_BOB_XMR,
                                               'get_balance')['balance']

        logging.info(
            'Test start wallet states:\nalice_btc_start: %ld\nbob_btc_start: %ld\nalice_xmr_start: %ld\nbob_xmr_start: %ld',
            alice_btc_start, bob_btc_start, alice_xmr_start, bob_xmr_start)

        self.startSwap(ID_ALICE_SWAP, ID_BOB_SWAP, 2, 3)

        logging.info(
            'Alice creates the script-chain lock and refund txns and signs the refund tx, sends to Bob.'
        )
        msg2f = callSwapTool(ID_ALICE_SWAP, 'msg2f')

        logging.info(
            'Bob verifies the txns and signs the refund tx and creates an encrypted signature for the refund spend tx encumbered by Alice\'s coin B key share.'
        )
        callSwapTool(ID_BOB_SWAP, 'processmsg', str_param=msg2f)
        msg3l = callSwapTool(ID_BOB_SWAP, 'msg3l')

        logging.info(
            'Alice verifies the signature and encrypted signature from Bob.')
        callSwapTool(ID_ALICE_SWAP, 'processmsg', str_param=msg3l)

        logging.info(
            'Creates the lock spend tx and signs an encrypted signature encumbered by Bob\'s coin B key share'
        )
        msg4f = callSwapTool(ID_ALICE_SWAP, 'msg4f')

        logging.info('Publishes the script-chain lock tx.')
        a_lock_txid = callSwapTool(ID_ALICE_SWAP, 'publishalocktx').strip()

        # Wait for the mining node to receive the tx
        for i in range(10):
            try:
                callnoderpc(0, 'getrawtransaction', [a_lock_txid])
                break
            except Exception as e:
                print('Waiting for node 0 to see tx', str(e))
            time.sleep(1)

        logging.info('Bob stops responding here.')

        alice_btc = make_int(
            callnoderpc(ID_ALICE_PART, 'getbalances')['mine']['trusted'])
        logging.info('alice_btc %ld', alice_btc)

        a_lock_refund_txid = self.publishALockRefundTx(ID_ALICE_PART,
                                                       ID_ALICE_SWAP)

        # Import key to receive refund in wallet.  Simple method for testing.
        kal = callSwapTool(ID_ALICE_SWAP, 'getkal')
        kal_wif = bytes_to_wif(h2b(kal), prefix=0x2e)
        callnoderpc(ID_ALICE_PART, 'importprivkey', [kal_wif, 'swap refund'])

        alockrefundspendtxid = callSwapTool(ID_ALICE_SWAP,
                                            'publishalockrefundspendtx')

        rv = callnoderpc(ID_ALICE_PART, 'getbalances')
        alice_btc_end = make_int(rv['mine']['trusted']) + make_int(
            rv['mine']['untrusted_pending'])
        logging.info('alice_btc_end %ld', alice_btc_end)

        assert (alice_btc_end > alice_btc)
示例#7
0
def initialiseSwap(swapinfo, data):
    try:
        a_coin = CoinIds[data['a_coin']]
    except Exception as e:
        raise ValueError('Unknown A coin type')

    # Coin A must have a script
    if a_coin == CoinIds.XMR:
        raise ValueError('Bad A coin type')

    try:
        b_coin = CoinIds[data['b_coin']]
    except Exception as e:
        raise ValueError('Unknown B coin type')

    swapinfo.a_connect = data['a_connect']
    swapinfo.b_connect = data['b_connect']
    ai = makeInterface(a_coin, swapinfo.a_connect)
    bi = makeInterface(b_coin, swapinfo.b_connect)

    a_amount = make_int(data['a_amount'], ai.exp())
    b_amount = make_int(data['b_amount'], bi.exp())

    a_feerate = make_int(data['a_feerate'], ai.exp())
    b_feerate = make_int(data['b_feerate'], bi.exp())

    if 'a_addr_f' in data:
        # Decode p2wpkh address
        addr = data['a_addr_f']
        addr_split = addr.split('1')
        if len(addr_split) != 2:
            raise ValueError('Invalid bech32 address')

        if addr_split[0] not in ['bc', 'pw', 'bcrt', 'rtpw']:
            raise ValueError('Unknown bech32 hrp')

        ignr, pkh = segwit_addr.decode(addr_split[0], addr)
        a_pkhash_f = bytes(pkh)
    else:
        a_pkhash_f = h2b(data['a_pkhash_f'])

    lock1 = data['lock1'] if 'lock1' in data else 100
    lock2 = data['lock2'] if 'lock2' in data else 101

    restore_height_b = data[
        'b_restore_height'] if 'b_restore_height' in data else 0

    check_a_lock_tx_inputs = data[
        'check_a_lock_tx_inputs'] if 'check_a_lock_tx_inputs' in data else True

    swapinfo.setSwapParameters(a_coin,
                               a_amount,
                               b_coin,
                               b_amount,
                               a_feerate,
                               b_feerate,
                               a_pkhash_f,
                               lock1=lock1,
                               lock2=lock2,
                               restore_height_b=restore_height_b,
                               check_a_lock_tx_inputs=check_a_lock_tx_inputs)

    if data['side'].lower() == 'a':
        swapinfo.initialiseLeader(ai, bi)
    elif data['side'].lower() == 'b':
        swapinfo.initialiseFollower(ai, bi)
    else:
        raise ValueError('Unknown swap side')