def setUp(self):
     load_test_config()
     self.clean_out_wallet_files()
     jm_single().bc_interface.tick_forward_chain_interval = 5
     jm_single().bc_interface.simulate_blocks()
     # a client connnection object which is often but not always
     # instantiated:
     self.client_connector = None
     # start the daemon; note we are using tcp connections
     # to avoid storing certs in the test env.
     # TODO change that.
     self.daemon = JMWalletDaemonT(self.dport, self.wss_port, tls=False)
     self.daemon.auth_disabled = False
     # because we sync and start the wallet service manually here
     # (and don't use wallet files yet), we won't have set a wallet name,
     # so we set it here:
     self.daemon.wallet_name = self.get_wallet_file_name(1)
     r, s = self.daemon.startService()
     self.listener_rpc = r
     self.listener_ws = s
     wallet_structures = [self.wallet_structure] * 2
     # note: to test fidelity bond wallets we should add the argument
     # `wallet_cls=SegwitWalletFidelityBonds` here, but it slows the
     # test down from 9 seconds to 1 minute 40s, which is too slow
     # to be acceptable. TODO: add a test with FB by speeding up
     # the sync for test, by some means or other.
     self.daemon.services["wallet"] = make_wallets_to_list(
         make_wallets(1,
                      wallet_structures=[wallet_structures[0]],
                      mean_amt=self.mean_amt,
                      wallet_cls=SegwitWalletFidelityBonds))[0]
     jm_single().bc_interface.tickchain()
     sync_wallets([self.daemon.services["wallet"]])
     # dummy tx example to force a notification event:
     self.test_tx = CTransaction.deserialize(hextobin(test_tx_hex_1))
示例#2
0
def test_simple_payjoin(monkeypatch, tmpdir, setup_cj, wallet_cls,
                        wallet_structures, mean_amt):
    def raise_exit(i):
        raise Exception("sys.exit called")
    monkeypatch.setattr(sys, 'exit', raise_exit)
    wallet_services = []
    wallet_services.append(make_wallets_to_list(make_wallets(
        1, wallet_structures=[wallet_structures[0]],
        mean_amt=mean_amt, wallet_cls=wallet_cls[0]))[0])
    wallet_services.append(make_wallets_to_list(make_wallets(
            1, wallet_structures=[wallet_structures[1]],
            mean_amt=mean_amt, wallet_cls=wallet_cls[1]))[0])
    jm_single().bc_interface.tickchain()
    sync_wallets(wallet_services)

    # For accounting purposes, record the balances
    # at the start.
    msb = getbals(wallet_services[0], 0)
    tsb = getbals(wallet_services[1], 0)

    cj_amount = int(1.1 * 10**8)
    maker = P2EPMaker(wallet_services[0], 0, cj_amount)
    destaddr = maker.destination_addr
    monkeypatch.setattr(maker, 'user_check', dummy_user_check)
    # TODO use this to sanity check behaviour
    # in presence of the rest of the joinmarket orderbook.
    orderbook = create_orderbook([maker])
    assert len(orderbook) == 1
    # mixdepth, amount, counterparties, dest_addr, waittime;
    # in payjoin we only pay attention to the first two entries.
    schedule = [(0, cj_amount, 1, destaddr, 0)]
    taker = create_taker(wallet_services[-1], schedule, monkeypatch)
    monkeypatch.setattr(taker, 'user_check', dummy_user_check)
    init_data = taker.initialize(orderbook)
    # the P2EPTaker.initialize() returns:
    # (True, self.cjamount, "p2ep", "p2ep", {self.p2ep_receiver_nick:{}})
    assert init_data[0], "taker.initialize error"
    active_orders = init_data[4]
    assert len(active_orders.keys()) == 1
    response = taker.receive_utxos(list(active_orders.keys()))
    assert response[0], "taker receive_utxos error"
    # test for validity of signed fallback transaction; requires 0.17;
    # note that we count this as an implicit test of fallback mode.
    res = jm_single().bc_interface.rpc('testmempoolaccept', [[response[2]]])
    assert res[0]["allowed"], "Proposed transaction was rejected from mempool."
    maker_response = maker.on_tx_received("faketaker", response[2])
    if not maker_response[0]:
        print("maker on_tx_received failed, reason: ", maker_response[1])
        assert False
    taker_response = taker.on_tx_received("fakemaker", maker_response[2])
    if not taker_response[1] == "OK":
        print("Failure in taker on_tx_received, reason: ", taker_response[1])
        assert False
    # Although the above OK is proof that a transaction went through,
    # it doesn't prove it was a good transaction! Here do balance checks:
    assert final_checks(wallet_services, cj_amount, taker.total_txfee, tsb, msb)
示例#3
0
    def do_test_payment(self, wc1, wc2, amt=1.1):
        wallet_structures = [self.wallet_structure] * 2
        wallet_cls = (wc1, wc2)
        self.wallet_services = []
        self.wallet_services.append(make_wallets_to_list(make_wallets(
            1, wallet_structures=[wallet_structures[0]],
            mean_amt=self.mean_amt, wallet_cls=wallet_cls[0]))[0])
        self.wallet_services.append(make_wallets_to_list(make_wallets(
                1, wallet_structures=[wallet_structures[1]],
                mean_amt=self.mean_amt, wallet_cls=wallet_cls[1]))[0])
        jm_single().bc_interface.tickchain()
        sync_wallets(self.wallet_services)

        # For accounting purposes, record the balances
        # at the start.
        self.rsb = getbals(self.wallet_services[0], 0)
        self.ssb = getbals(self.wallet_services[1], 0)

        self.cj_amount = int(amt * 10**8)
        def cbStopListening():
            return self.port.stopListening()
        b78rm = JMBIP78ReceiverManager(self.wallet_services[0], 0,
                                       self.cj_amount, 47083)
        resource = DummyBIP78ReceiverResource(jmprint, cbStopListening, b78rm)
        self.site = Site(resource)
        self.site.displayTracebacks = False
        # NB The connectivity aspects of the onion-based BIP78 setup
        # are time heavy. This server is TCP only.
        self.port = reactor.listenTCP(47083, self.site)
        self.addCleanup(cbStopListening)

        # setup of spender
        bip78_btc_amount = amount_to_btc(amount_to_sat(self.cj_amount))
        bip78_uri = encode_bip21_uri(str(b78rm.receiving_address),
                                {"amount": bip78_btc_amount,
                                 "pj": b"http://127.0.0.1:47083"},
                                safe=":/")
        self.manager = parse_payjoin_setup(bip78_uri, self.wallet_services[1], 0)
        self.manager.mode = "testing"
        success, msg = make_payment_psbt(self.manager)
        assert success, msg
        params = make_payjoin_request_params(self.manager)
        # avoiding backend daemon (testing only jmclient code here),
        # we send the http request manually:
        serv = b"http://127.0.0.1:47083"
        agent = get_nontor_agent()
        body = BytesProducer(self.manager.initial_psbt.to_base64().encode("utf-8"))
        url_parts = list(wrapped_urlparse(serv))
        url_parts[4] = urlencode(params).encode("utf-8")
        destination_url = urlparse.urlunparse(url_parts)
        d = agent.request(b"POST", destination_url,
                          Headers({"Content-Type": ["text/plain"]}),
                          bodyProducer=body)
        d.addCallback(bip78_receiver_response, self.manager)
        return d
def final_checks(wallet_services, amount, txfee, ssb, rsb, source_mixdepth=0):
    """We use this to check that the wallet contents are
    as we've expected according to the test case.
    amount is the payment amount going from spender to receiver.
    txfee is the bitcoin network transaction fee, paid by the spender.
    ssb, rsb are spender and receiver starting balances, each a tuple
    of two entries, source and destination mixdepth respectively.
    """
    jm_single().bc_interface.tickchain()
    sync_wallets(wallet_services)
    spenderbals = getbals(wallet_services[1], source_mixdepth)
    receiverbals = getbals(wallet_services[0], source_mixdepth)
    # is the payment received?
    receiver_newcoin_amt = receiverbals[1] - rsb[1]
    if not receiver_newcoin_amt >= amount:
        print("Receiver expected to receive at least: ", amount, " but got: ",
              receiver_newcoin_amt)
        return False
    # assert that the receiver received net exactly the right amount
    receiver_spentcoin_amt = rsb[0] - receiverbals[0]
    if not receiver_spentcoin_amt >= 0:
        # for now allow the non-cj fallback case
        print("receiver's spent coin should have been positive, was: ",
              receiver_spentcoin_amt)
        return False
    if not receiver_newcoin_amt == amount + receiver_spentcoin_amt:
        print("receiver's new coins should have been: ",
              amount + receiver_spentcoin_amt, " but was: ",
              receiver_newcoin_amt)
        return False

    # Spender-side check
    # assert that the spender's total ending minus total starting
    # balance is the amount plus the txfee given.
    if not (sum(spenderbals) - sum(ssb) + txfee + amount) == 0:
        print("Taker should have spent: ", txfee + amount, " but spent: ",
              sum(ssb) - sum(spenderbals))
        return False
    print("Final checks were passed")
    return True