Ejemplo n.º 1
0
def test_run_both(setup_wallets, runtype):
    #hack to account for the fact that Carol does not even run
    #if the handshake is bad; this is done to force the reactor to stop.
    if runtype == "badhandshake":
        cs_single().num_entities_running = 1
    #The setup of each test case is the same; the only difference is the
    #participant classes (only Alice for now)
    ac = alice_classes[runtype] if runtype in alice_classes else None
    cc = carol_classes[runtype] if runtype in carol_classes else None
    fail_alice_state = alice_recover_cases[
        runtype] if runtype in alice_recover_cases else None
    fail_carol_state = carol_recover_cases[
        runtype] if runtype in carol_recover_cases else None
    alices, carol_bbmb, carol_wallet = runcase(ac, cc, fail_alice_state,
                                               fail_carol_state)
    #test case function will only return on reactor shutdown; Alice and Carol
    #objects are set at the start, but are references so updated.
    #Check the wallet states reflect the expected updates.
    #TODO handle multiple alices with different amounts against one Carol.
    if runtype == "badhandshake":
        for a in alices:
            a.bbma = a.wallet.get_balance_by_mixdepth(verbose=False)

    expected_spent = reasonable_fee_maximum*4 + cs_single(
        ).config.getint("SERVER", "minimum_coinswap_fee")
    if runtype in alice_funds_not_moved_cases:
        for i, alice in enumerate(alices):
            assert alice.bbmb[0] == alice.bbma[0]
    elif runtype in ["cooperative", "cbadreceivetx4sig", "ra11", "rc8", "rc9"]:
        #in all of these cases Alice's payment is complete
        for i, alice in enumerate(alices):
            funds_spent = alice.bbmb[0] - alice.bbma[0]
            funds_received = alice.bbma[1] - alice.bbmb[1]
            assert funds_spent - funds_received <= expected_spent + reasonable_fee_maximum
    else:
        #Ensure Alice did not pay too much and only spent back to 0 depth
        for i, alice in enumerate(alices):
            assert alice.bbma[1] == 0
            funds_spent = alice.bbmb[0] - alice.bbma[0]
            assert funds_spent <= expected_spent

    #Carol is handled a bit differently, since Carol instances are initiated on
    #the fly, we instead query the wallet object directly for the final balances.
    sync_wallet(carol_wallet)
    carol_bbma = carol_wallet.get_balance_by_mixdepth(verbose=False)
    if runtype in carol_funds_not_moved_cases:
        assert carol_bbma[0] >= carol_bbmb[0]
        assert carol_bbma[0] - carol_bbmb[0] <= reasonable_fee_maximum + cs_single(
            ).config.getint("SERVER", "minimum_coinswap_fee")
    elif runtype in ["cooperative", "rc9"]:
        funds_spent = carol_bbmb[0] - carol_bbma[0]
        funds_received = carol_bbma[1] - carol_bbmb[1]
        assert funds_received - funds_spent >= cs_single(
            ).config.getint("SERVER", "minimum_coinswap_fee") - reasonable_fee_maximum
    else:
        #All cases of backout and funds have moved
        assert carol_bbmb[1] == 0
        #Here we assert carol did not lose money; the alice checks are sufficient
        #to ensure carol didn't get too much
        assert carol_bbma[0] - carol_bbmb[0] > 0
Ejemplo n.º 2
0
def test_run_both(setup_wallets, runtype):
    #hack to account for the fact that Carol does not even run
    #if the handshake is bad; this is done to force the reactor to stop.
    if runtype == "badhandshake":
        cs_single().num_entities_running = 1
    #The setup of each test case is the same; the only difference is the
    #participant classes (only Alice for now)
    ac = alice_classes[runtype] if runtype in alice_classes else None
    cc = carol_classes[runtype] if runtype in carol_classes else None
    alices, carol_bbmb, carol_wallet = runcase(ac, cc)
    #test case function will only return on reactor shutdown; Alice and Carol
    #objects are set at the start, but are references so updated.
    #Check the wallet states reflect the expected updates.
    #TODO handle multiple alices with different amounts against one Carol.
    expected_amt = amounts[0] - reasonable_fee_maximum
    if runtype in alice_funds_not_moved_cases:
        for i, alice in enumerate(alices):
            assert alice.bbmb[0] == alice.bbma[0]
    else:
        for i, alice in enumerate(alices):
            funds_spent = alice.bbmb[0] - alice.bbma[0]
            funds_received = alice.bbma[1] - alice.bbmb[1]
            assert_funds_balance(expected_amt, funds_spent, funds_received)
    #Carol is handled a bit differently, since Carol instances are initiated on
    #the fly, we instead query the wallet object directly for the final balances.
    sync_wallet(carol_wallet)
    carol_bbma = carol_wallet.get_balance_by_mixdepth(verbose=False)
    if runtype in carol_funds_not_moved_cases:
        assert carol_bbma[0] == carol_bbmb[0]
    else:
        funds_spent = carol_bbmb[0] - carol_bbma[0]
        funds_received = carol_bbma[1] - carol_bbmb[1]
        assert_funds_balance(expected_amt, funds_spent, funds_received)
Ejemplo n.º 3
0
def main_cs(test_data=None):
    #twisted logging (TODO disable for non-debug runs)
    if test_data:
        wallet_name, args, options, use_ssl, alt_class, alt_c_class = test_data
    else:
        log.startLogging(sys.stdout)
        #Joinmarket wallet
        parser = get_coinswap_parser()
        (options, args) = parser.parse_args()
        load_coinswap_config()
        wallet_name = args[0]
    #depth 0: spend in, depth 1: receive out, depth 2: for backout transactions.
    max_mix_depth = 3
    if not os.path.exists(os.path.join('wallets', wallet_name)):
        wallet = Wallet(wallet_name, None, max_mix_depth, 6)
    else:
        while True:
            try:
                pwd = get_password("Enter wallet decryption passphrase: ")
                wallet = Wallet(wallet_name, pwd, max_mix_depth, 6)
            except WalletError:
                print("Wrong password, try again.")
                continue
            except Exception as e:
                print("Failed to load wallet, error message: " + repr(e))
                sys.exit(0)
            break
    #for testing main script (not test framework), need funds.
    if not test_data and isinstance(cs_single().bc_interface,
                                    RegtestBitcoinCoreInterface):
        cs_single().bc_interface.grab_coins(wallet.get_new_addr(0, 0), 2.0)
        time.sleep(3)
    sync_wallet(wallet, fast=options.fastsync)
    wallet.used_coins = None
    if options.serve:
        #sanity check that client params were not provided:
        if len(args) > 1:
            print("Extra parameters provided for running as server. "
                  "Are you sure you didn't want to run as client?")
            sys.exit(0)
        if not test_data:
            main_server(options, wallet)
        else:
            main_server(options, wallet, {
                'use_ssl': use_ssl,
                'alt_c_class': alt_c_class
            })
            return wallet.get_balance_by_mixdepth()
        return
    tx01_amount = int(args[1])
    #Reset the targetting for backout transactions
    oldtarget = cs_single().config.get("POLICY", "tx_fees")
    newtarget = cs_single().config.getint("POLICY", "backout_fee_target")
    multiplier = float(cs_single().config.get("POLICY",
                                              "backout_fee_multiplier"))
    cs_single().config.set("POLICY", "tx_fees", str(newtarget))
    tx23fee = estimate_tx_fee((1, 2, 2), 1, txtype='p2shMofN')
    tx23fee = int(multiplier * tx23fee)
    tx24_recipient_amount = tx01_amount - tx23fee
    tx35_recipient_amount = tx01_amount - tx23fee
    cs_single().config.set("POLICY", "tx_fees", oldtarget)
    #to allow testing of confirm/unconfirm callback for multiple txs
    if isinstance(cs_single().bc_interface, RegtestBitcoinCoreInterface):
        cs_single().bc_interface.tick_forward_chain_interval = 2
        cs_single().bc_interface.simulating = True
        cs_single().config.set("BLOCKCHAIN", "notify_port", "62652")
        cs_single().config.set("BLOCKCHAIN", "rpc_host", "127.0.0.2")

    #if restart option selected, read state and backout
    if options.recover:
        session_id = options.recover
        alice = CoinSwapAlice(wallet, 'alicestate')
        alice.bbmb = wallet.get_balance_by_mixdepth(verbose=False)
        alice.load(sessionid=session_id)
        alice.backout("Recovering from shutdown")
        reactor.run()
        return
    if len(args) > 2:
        tx5address = args[2]
        if not validate_address(tx5address):
            print("Invalid address: ", tx5address)
            sys.exit(0)
    else:
        #Our destination address should be in a separate mixdepth
        tx5address = wallet.get_new_addr(1, 1)
    #instantiate the parameters, but don't yet have the ephemeral pubkeys
    #or destination addresses.
    cpp = CoinSwapPublicParameters(tx01_amount, tx24_recipient_amount,
                                   tx35_recipient_amount)
    #Alice must set the unique identifier for this run.
    cpp.set_session_id()
    cpp.set_tx5_address(tx5address)
    testing_mode = True if test_data else False
    aliceclass = alt_class if test_data and alt_class else CoinSwapAlice
    alice = aliceclass(wallet, 'alicestate', cpp, testing_mode=testing_mode)
    scheme, server, port = options.serverport.split(":")
    print("got this scheme, server, port: ", scheme, server, port)
    if scheme == "https":
        usessl = True
    elif scheme == "http":
        usessl = False
    else:
        print("Invalid server string: ", options.serverport)
        sys.exit(0)
    if not server[:2] == "//":
        print("Invalid server string: ", options.serverport)
    alice_client = CoinSwapJSONRPCClient(server[2:], port, alice.sm.tick,
                                         alice.backout, usessl)
    alice.set_jsonrpc_client(alice_client)
    reactor.callWhenRunning(alice.sm.tick)
    if not test_data:
        reactor.run()
    if test_data:
        return alice
Ejemplo n.º 4
0
def main_cs(test_data=None):
    #twisted logging (TODO disable for non-debug runs)
    if test_data:
        wallet_name, args, options, use_ssl, alt_class, alt_c_class, fail_alice_state, fail_carol_state = test_data
        server, port, usessl = parse_server_string(options.serverport)
    else:
        parser = get_coinswap_parser()
        (options, args) = parser.parse_args()
        #Will only be used by client
        server, port, usessl = parse_server_string(options.serverport)
        if options.checkonly:
            #no need for any more data; just query
            alice_client = CoinSwapJSONRPCClient(server[2:], port, usessl=usessl)
            reactor.callWhenRunning(alice_client.send_poll_unsigned,
                                    "status", print_status)
            reactor.run()
            return
        log.startLogging(sys.stdout)
        load_coinswap_config()
        wallet_name = args[0]
    #depth 0: spend in, depth 1: receive out, depth 2: for backout transactions.
    max_mix_depth = 3
    wallet_dir = os.path.join(cs_single().homedir, 'wallets')
    if not os.path.exists(os.path.join(wallet_dir, wallet_name)):
        wallet = Wallet(wallet_name, None, max_mix_depth, 6,
                        wallet_dir=wallet_dir)
    else:
        while True:
            try:
                pwd = get_password("Enter wallet decryption passphrase: ")
                wallet = Wallet(wallet_name, pwd, max_mix_depth, 6,
                                wallet_dir=wallet_dir)
            except WalletError:
                print("Wrong password, try again.")
                continue
            except Exception as e:
                print("Failed to load wallet, error message: " + repr(e))
                sys.exit(0)
            break
    #for testing main script (not test framework), need funds.
    if not test_data and isinstance(
        cs_single().bc_interface, RegtestBitcoinCoreInterface):
        cs_single().bc_interface.grab_coins(wallet.get_new_addr(0, 0, True), 2.0)
        wallet.index[0][0] -= 1
        time.sleep(3)
    sync_wallet(wallet, fast=options.fastsync)
    if test_data:
        cs_single().bc_interface.wallet_synced = True
    wallet.used_coins = None
    if options.serve:
        #sanity check that client params were not provided:
        if len(args) > 1:
            print("Extra parameters provided for running as server. "
                  "Are you sure you didn't want to run as client?")
            sys.exit(0)
        if not test_data:
            main_server(options, wallet)
        else:
            main_server(options, wallet, {'use_ssl': use_ssl,
                                          'alt_c_class': alt_c_class,
                                          'fail_carol_state': fail_carol_state})
            return wallet.get_balance_by_mixdepth()
        return
    if not options.recover:
        target_amount = int(args[1])
        #Reset the targetting for backout transactions
        #TODO must be removed/changed for updated fees handling
        oldtarget = cs_single().config.get("POLICY", "tx_fees")
        newtarget = cs_single().config.getint("POLICY", "backout_fee_target")
        multiplier = float(cs_single().config.get("POLICY", "backout_fee_multiplier"))
        cs_single().config.set("POLICY", "tx_fees", str(newtarget))
        tx23fee = estimate_tx_fee((1, 2, 2), 1, txtype='p2shMofN')
        tx23fee = int(multiplier * tx23fee)
        tx24_recipient_amount = target_amount - tx23fee
        tx35_recipient_amount = target_amount - tx23fee
        cs_single().config.set("POLICY", "tx_fees", oldtarget)
    #to allow testing of confirm/unconfirm callback for multiple txs
    if isinstance(cs_single().bc_interface, RegtestBitcoinCoreInterface):
        cs_single().bc_interface.tick_forward_chain_interval = 2
        cs_single().bc_interface.simulating = True
        cs_single().config.set("BLOCKCHAIN", "notify_port", "62652")
        cs_single().config.set("BLOCKCHAIN", "rpc_host", "127.0.0.2")
    
    #if restart option selected, read state and backout
    if options.recover:
        session_id = options.recover
        alice = CoinSwapAlice(wallet, 'alicestate')
        alice.bbmb = wallet.get_balance_by_mixdepth(verbose=False)
        alice.load(sessionid=session_id)
        alice.backout("Recovering from shutdown")
        reactor.run()
        return
    if len(args) > 2:
        tx5address = args[2]
        if not validate_address(tx5address):
            print("Invalid address: ", tx5address)
            sys.exit(0)
    else:
        #Our destination address should be in a separate mixdepth
        tx5address = wallet.get_new_addr(1, 1, True)
    #instantiate the parameters, but don't yet have the ephemeral pubkeys
    #or destination addresses.
    #TODO figure out best estimate incl. priority
    btcfee_est = estimate_tx_fee((1, 2, 2), 1, txtype='p2shMofN')
    cpp = CoinSwapPublicParameters(base_amount=target_amount, bitcoin_fee=btcfee_est)
    cpp.set_addr_data(addr5=tx5address)
    testing_mode = True if test_data else False
    aliceclass = alt_class if test_data and alt_class else CoinSwapAlice
    if test_data and fail_alice_state:
        alice = aliceclass(wallet, 'alicestate', cpp, testing_mode=testing_mode,
                           fail_state=fail_alice_state)
    else:
        alice = aliceclass(wallet, 'alicestate', cpp, testing_mode=testing_mode)

    alice_client = CoinSwapJSONRPCClient(server[2:], port,
                                         alice.sm.tick, alice.backout, usessl)
    alice.set_jsonrpc_client(alice_client)
    reactor.callWhenRunning(alice_client.send_poll_unsigned, "status",
                            alice.check_server_status)
    if not test_data:
        reactor.run()
    if test_data:
        return alice
Ejemplo n.º 5
0
                        extend_mixdepth=not maxmixdepth_configured,
                        storepassword=(method == 'importprivkey'))
            except WalletError:
                print("Wrong password, try again.")
                continue
            except Exception as e:
                print("Failed to load wallet, error message: " + repr(e))
                sys.exit(0)
            break
    if method not in noscan_methods:
        # if nothing was configured, we override bitcoind's options so that
        # unconfirmed balance is included in the wallet display by default
        if 'listunspent_args' not in cs_single().config.options('POLICY'):
            cs_single().config.set('POLICY','listunspent_args', '[0]')

        sync_wallet(wallet, fast=options.fastsync)

if method == 'showutxos':
    unsp = {}
    if options.showprivkey:
        for u, av in wallet.unspent.iteritems():
            addr = av['address']
            key = wallet.get_key_from_addr(addr)
            wifkey = btc.wif_compressed_privkey(key, vbyte=get_p2pk_vbyte())
            unsp[u] = {'address': av['address'],
                       'value': av['value'], 'privkey': wifkey}
    else:
        unsp = wallet.unspent
    print(json.dumps(unsp, indent=4))
    sys.exit(0)