def test_verify_tx_input(setup_tx_creation):
    priv = b"\xaa" * 32 + b"\x01"
    pub = bitcoin.privkey_to_pubkey(priv)
    script = bitcoin.pubkey_to_p2sh_p2wpkh_script(pub)
    addr = str(bitcoin.CCoinAddress.from_scriptPubKey(script))
    wallet_service = make_wallets(1, [[2, 0, 0, 0, 0]], 1)[0]['wallet']
    wallet_service.sync_wallet(fast=True)
    insfull = wallet_service.select_utxos(0, 110000000)
    outs = [{"address": addr, "value": 1000000}]
    ins = list(insfull.keys())
    tx = bitcoin.mktx(ins, outs)
    scripts = {0: (insfull[ins[0]]["script"], bitcoin.coins_to_satoshi(1))}
    success, msg = wallet_service.sign_tx(tx, scripts)
    assert success, msg
    # testing Joinmarket's ability to verify transaction inputs
    # of others: pretend we don't have a wallet owning the transaction,
    # and instead verify an input using the (sig, pub, scriptCode) data
    # that is sent by counterparties:
    cScrWit = tx.wit.vtxinwit[0].scriptWitness
    sig = cScrWit.stack[0]
    pub = cScrWit.stack[1]
    scriptSig = tx.vin[0].scriptSig
    tx2 = bitcoin.mktx(ins, outs)
    res = bitcoin.verify_tx_input(tx2,
                                  0,
                                  scriptSig,
                                  bitcoin.pubkey_to_p2wpkh_script(pub),
                                  amount=bitcoin.coins_to_satoshi(1),
                                  witness=bitcoin.CScriptWitness([sig, pub]))
    assert res
def test_create_and_sign_psbt_with_legacy(setup_psbt_wallet):
    """ The purpose of this test is to check that we can create and
    then partially sign a PSBT where we own one input and the other input
    is of legacy p2pkh type.
    """
    wallet_service = make_wallets(1, [[1, 0, 0, 0, 0]], 1)[0]['wallet']
    wallet_service.sync_wallet(fast=True)
    utxos = wallet_service.select_utxos(0, bitcoin.coins_to_satoshi(0.5))
    assert len(utxos) == 1
    # create a legacy address and make a payment into it
    legacy_addr = bitcoin.CCoinAddress.from_scriptPubKey(
        bitcoin.pubkey_to_p2pkh_script(bitcoin.privkey_to_pubkey(b"\x01" *
                                                                 33)))
    tx = direct_send(wallet_service,
                     bitcoin.coins_to_satoshi(0.3),
                     0,
                     str(legacy_addr),
                     accept_callback=dummy_accept_callback,
                     info_callback=dummy_info_callback,
                     return_transaction=True)
    assert tx
    # this time we will have one utxo worth <~ 0.7
    my_utxos = wallet_service.select_utxos(0, bitcoin.coins_to_satoshi(0.5))
    assert len(my_utxos) == 1
    # find the outpoint for the legacy address we're spending
    n = -1
    for i, t in enumerate(tx.vout):
        if bitcoin.CCoinAddress.from_scriptPubKey(
                t.scriptPubKey) == legacy_addr:
            n = i
    assert n > -1
    utxos = copy.deepcopy(my_utxos)
    utxos[(tx.GetTxid()[::-1], n)] = {
        "script": legacy_addr.to_scriptPubKey(),
        "value": bitcoin.coins_to_satoshi(0.3)
    }
    outs = [{
        "value": bitcoin.coins_to_satoshi(0.998),
        "address": wallet_service.get_addr(0, 0, 0)
    }]
    tx2 = bitcoin.mktx(list(utxos.keys()), outs)
    spent_outs = wallet_service.witness_utxos_to_psbt_utxos(my_utxos)
    spent_outs.append(tx)
    new_psbt = wallet_service.create_psbt_from_tx(tx2,
                                                  spent_outs,
                                                  force_witness_utxo=False)
    signed_psbt_and_signresult, err = wallet_service.sign_psbt(
        new_psbt.serialize(), with_sign_result=True)
    assert err is None
    signresult, signed_psbt = signed_psbt_and_signresult
    assert signresult.num_inputs_signed == 1
    assert signresult.num_inputs_final == 1
    assert not signresult.is_final
Exemplo n.º 3
0
def test_sign_standard_txs(addrtype):
    # liberally copied from python-bitcoinlib tests,
    # in particular see:
    # https://github.com/petertodd/python-bitcoinlib/pull/227

    # Create the (in)famous correct brainwallet secret key.
    priv = hashlib.sha256(b'correct horse battery staple').digest() + b"\x01"
    pub = btc.privkey_to_pubkey(priv)

    # Create an address from that private key.
    # (note that the input utxo is fake so we are really only creating
    # a destination here).
    scriptPubKey = btc.CScript([btc.OP_0, btc.Hash160(pub)])
    address = btc.P2WPKHCoinAddress.from_scriptPubKey(scriptPubKey)

    # Create a dummy outpoint; use same 32 bytes for convenience
    txid = priv[:32]
    vout = 2
    amount = btc.coins_to_satoshi(float('0.12345'))

    # Calculate an amount for the upcoming new UTXO. Set a high fee to bypass
    # bitcoind minfee setting.
    amount_less_fee = int(amount - btc.coins_to_satoshi(0.01))

    # Create a destination to send the coins.
    destination_address = address
    target_scriptPubKey = scriptPubKey

    # Create the unsigned transaction.
    txin = btc.CTxIn(btc.COutPoint(txid[::-1], vout))
    txout = btc.CTxOut(amount_less_fee, target_scriptPubKey)
    tx = btc.CMutableTransaction([txin], [txout])

    # Calculate the signature hash for the transaction. This is then signed by the
    # private key that controls the UTXO being spent here at this txin_index.
    if addrtype == "p2wpkh":
        sig, msg = btc.sign(tx, 0, priv, amount=amount, native="p2wpkh")
    elif addrtype == "p2sh-p2wpkh":
        sig, msg = btc.sign(tx, 0, priv, amount=amount, native=False)
    elif addrtype == "p2pkh":
        sig, msg = btc.sign(tx, 0, priv)
    else:
        assert False
    if not sig:
        print(msg)
        raise
    print("created signature: ", bintohex(sig))
    print("serialized transaction: {}".format(bintohex(tx.serialize())))
    print("deserialized transaction: {}\n".format(
        btc.human_readable_transaction(tx)))
def test_mk_shuffled_tx():
    # prepare two addresses for the outputs
    pub = btc.privkey_to_pubkey(btc.Hash(b"priv") + b"\x01")
    scriptPubKey = btc.CScript([btc.OP_0, btc.Hash160(pub)])
    addr1 = btc.P2WPKHCoinAddress.from_scriptPubKey(scriptPubKey)
    scriptPubKey_p2sh = scriptPubKey.to_p2sh_scriptPubKey()
    addr2 = btc.CCoinAddress.from_scriptPubKey(scriptPubKey_p2sh)

    ins = [(btc.Hash(b"blah"), 7), (btc.Hash(b"foo"), 15)]
    # note the casts str() ; most calls to mktx will have addresses fed
    # as strings, so this is enforced for simplicity.
    outs = [{"address": str(addr1), "value": btc.coins_to_satoshi(float("0.1"))},
            {"address": str(addr2), "value": btc.coins_to_satoshi(float("45981.23331234"))}]
    tx = btc.make_shuffled_tx(ins, outs, version=2, locktime=500000)
def test_bip143_tv():
    # p2sh-p2wpkh case:
    rawtx_hex = "0100000001db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a54770100000000feffffff02b8b4eb0b000000001976a914a457b684d7f0d539a46a45bbc043f35b59d0d96388ac0008af2f000000001976a914fd270b1ee6abcaea97fea7ad0402e8bd8ad6d77c88ac92040000"
    inp_spk_hex = "a9144733f37cf4db86fbc2efed2500b4f4e49f31202387"
    value = 10
    redeemScript = "001479091972186c449eb1ded22b78e40d009bdf0089"
    privkey_hex = "eb696a065ef48a2192da5b28b694f87544b30fae8327c4510137a922f32c6dcf01"
    pubkey_hex = "03ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a26873"
    tx = btc.CMutableTransaction.deserialize(btc.x(rawtx_hex))
    btc.sign(tx, 0, btc.x(privkey_hex), amount=btc.coins_to_satoshi(10), native=False)
    expectedsignedtx = "01000000000101db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a5477010000001716001479091972186c449eb1ded22b78e40d009bdf0089feffffff02b8b4eb0b000000001976a914a457b684d7f0d539a46a45bbc043f35b59d0d96388ac0008af2f000000001976a914fd270b1ee6abcaea97fea7ad0402e8bd8ad6d77c88ac02473044022047ac8e878352d3ebbde1c94ce3a10d057c24175747116f8288e5d794d12d482f0220217f36a485cae903c713331d877c1f64677e3622ad4010726870540656fe9dcb012103ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a2687392040000"
    assert btc.b2x(tx.serialize()) == expectedsignedtx
def test_create_psbt_and_sign(setup_psbt_wallet, unowned_utxo, wallet_cls):
    """ Plan of test:
    1. Create a wallet and source 3 destination addresses.
    2. Make, and confirm, transactions that fund the 3 addrs.
    3. Create a new tx spending 2 of those 3 utxos and spending
       another utxo we don't own (extra is optional per `unowned_utxo`).
    4. Create a psbt using the above transaction and corresponding
       `spent_outs` field to fill in the redeem script.
    5. Compare resulting PSBT with expected structure.
    6. Use the wallet's sign_psbt method to sign the whole psbt, which
       means signing each input we own.
    7. Check that each input is finalized as per expected. Check that the whole
       PSBT is or is not finalized as per whether there is an unowned utxo.
    8. In case where whole psbt is finalized, attempt to broadcast the tx.
    """
    # steps 1 and 2:
    wallet_service = make_wallets(1, [[3, 0, 0, 0, 0]],
                                  1,
                                  wallet_cls=wallet_cls)[0]['wallet']
    wallet_service.sync_wallet(fast=True)
    utxos = wallet_service.select_utxos(0, bitcoin.coins_to_satoshi(1.5))
    # for legacy wallets, psbt creation requires querying for the spending
    # transaction:
    if wallet_cls == LegacyWallet:
        fulltxs = []
        for utxo, v in utxos.items():
            fulltxs.append(
                jm_single().bc_interface.get_deser_from_gettransaction(
                    jm_single().bc_interface.get_transaction(utxo[0])))

    assert len(utxos) == 2
    u_utxos = {}
    if unowned_utxo:
        # note: tx creation uses the key only; psbt creation uses the value,
        # which can be fake here; we do not intend to attempt to fully
        # finalize a psbt with an unowned input. See
        # https://github.com/Simplexum/python-bitcointx/issues/30
        # the redeem script creation (which is artificial) will be
        # avoided in future.
        priv = b"\xaa" * 32 + b"\x01"
        pub = bitcoin.privkey_to_pubkey(priv)
        script = bitcoin.pubkey_to_p2sh_p2wpkh_script(pub)
        redeem_script = bitcoin.pubkey_to_p2wpkh_script(pub)
        u_utxos[(b"\xaa" * 32, 12)] = {"value": 1000, "script": script}
    utxos.update(u_utxos)
    # outputs aren't interesting for this test (we selected 1.5 but will get 2):
    outs = [{
        "value": bitcoin.coins_to_satoshi(1.999),
        "address": wallet_service.get_addr(0, 0, 0)
    }]
    tx = bitcoin.mktx(list(utxos.keys()), outs)

    if wallet_cls != LegacyWallet:
        spent_outs = wallet_service.witness_utxos_to_psbt_utxos(utxos)
        force_witness_utxo = True
    else:
        spent_outs = fulltxs
        # the extra input is segwit:
        if unowned_utxo:
            spent_outs.extend(
                wallet_service.witness_utxos_to_psbt_utxos(u_utxos))
        force_witness_utxo = False
    newpsbt = wallet_service.create_psbt_from_tx(
        tx, spent_outs, force_witness_utxo=force_witness_utxo)
    # see note above
    if unowned_utxo:
        newpsbt.inputs[-1].redeem_script = redeem_script
    print(bintohex(newpsbt.serialize()))
    print("human readable: ")
    print(wallet_service.human_readable_psbt(newpsbt))
    # we cannot compare with a fixed expected result due to wallet randomization, but we can
    # check psbt structure:
    expected_inputs_length = 3 if unowned_utxo else 2
    assert len(newpsbt.inputs) == expected_inputs_length
    assert len(newpsbt.outputs) == 1
    # note: redeem_script field is a CScript which is a bytes instance,
    # so checking length is best way to check for existence (comparison
    # with None does not work):
    if wallet_cls == SegwitLegacyWallet:
        assert len(newpsbt.inputs[0].redeem_script) != 0
        assert len(newpsbt.inputs[1].redeem_script) != 0
    if unowned_utxo:
        assert newpsbt.inputs[2].redeem_script == redeem_script

    signed_psbt_and_signresult, err = wallet_service.sign_psbt(
        newpsbt.serialize(), with_sign_result=True)
    assert err is None
    signresult, signed_psbt = signed_psbt_and_signresult
    expected_signed_inputs = len(utxos) if not unowned_utxo else len(utxos) - 1
    assert signresult.num_inputs_signed == expected_signed_inputs
    assert signresult.num_inputs_final == expected_signed_inputs

    if not unowned_utxo:
        assert signresult.is_final
        # only in case all signed do we try to broadcast:
        extracted_tx = signed_psbt.extract_transaction().serialize()
        assert jm_single().bc_interface.pushtx(extracted_tx)
    else:
        # transaction extraction must fail for not-fully-signed psbts:
        with pytest.raises(ValueError) as e:
            extracted_tx = signed_psbt.extract_transaction()
def test_payjoin_workflow(setup_psbt_wallet, payment_amt, wallet_cls_sender,
                          wallet_cls_receiver):
    """ Workflow step 1:
    Create a payment from a wallet, and create a finalized PSBT.
    This step is fairly trivial as the functionality is built-in to
    PSBTWalletMixin.
    Note that only Segwit* wallets are supported for PayJoin.

        Workflow step 2:
    Receiver creates a new partially signed PSBT with the same amount
    and at least one more utxo.

        Workflow step 3:
    Given a partially signed PSBT created by a receiver, here the sender
    completes (co-signs) the PSBT they are given. Note this code is a PSBT
    functionality check, and does NOT include the detailed checks that
    the sender should perform before agreeing to sign (see:
    https://github.com/btcpayserver/btcpayserver-doc/blob/eaac676866a4d871eda5fd7752b91b88fdf849ff/Payjoin-spec.md#receiver-side
    ).
    """

    wallet_r = make_wallets(1, [[3, 0, 0, 0, 0]],
                            1,
                            wallet_cls=wallet_cls_receiver)[0]["wallet"]
    wallet_s = make_wallets(1, [[3, 0, 0, 0, 0]],
                            1,
                            wallet_cls=wallet_cls_sender)[0]["wallet"]
    for w in [wallet_r, wallet_s]:
        w.sync_wallet(fast=True)

    # destination address for payment:
    destaddr = str(
        bitcoin.CCoinAddress.from_scriptPubKey(
            bitcoin.pubkey_to_p2wpkh_script(
                bitcoin.privkey_to_pubkey(b"\x01" * 33))))

    payment_amt = bitcoin.coins_to_satoshi(payment_amt)

    # *** STEP 1 ***
    # **************

    # create a normal tx from the sender wallet:
    payment_psbt = direct_send(wallet_s,
                               payment_amt,
                               0,
                               destaddr,
                               accept_callback=dummy_accept_callback,
                               info_callback=dummy_info_callback,
                               with_final_psbt=True)

    print("Initial payment PSBT created:\n{}".format(
        wallet_s.human_readable_psbt(payment_psbt)))
    # ensure that the payemnt amount is what was intended:
    out_amts = [x.nValue for x in payment_psbt.unsigned_tx.vout]
    # NOTE this would have to change for more than 2 outputs:
    assert any([out_amts[i] == payment_amt for i in [0, 1]])

    # ensure that we can actually broadcast the created tx:
    # (note that 'extract_transaction' represents an implicit
    # PSBT finality check).
    extracted_tx = payment_psbt.extract_transaction().serialize()
    # don't want to push the tx right now, because of test structure
    # (in production code this isn't really needed, we will not
    # produce invalid payment transactions).
    res = jm_single().bc_interface.testmempoolaccept(bintohex(extracted_tx))
    assert res[0]["allowed"], "Payment transaction was rejected from mempool."

    # *** STEP 2 ***
    # **************

    # Simple receiver utxo choice heuristic.
    # For more generality we test with two receiver-utxos, not one.
    all_receiver_utxos = wallet_r.get_all_utxos()
    # TODO is there a less verbose way to get any 2 utxos from the dict?
    receiver_utxos_keys = list(all_receiver_utxos.keys())[:2]
    receiver_utxos = {
        k: v
        for k, v in all_receiver_utxos.items() if k in receiver_utxos_keys
    }

    # receiver will do other checks as discussed above, including payment
    # amount; as discussed above, this is out of the scope of this PSBT test.

    # construct unsigned tx for payjoin-psbt:
    payjoin_tx_inputs = [(x.prevout.hash[::-1], x.prevout.n)
                         for x in payment_psbt.unsigned_tx.vin]
    payjoin_tx_inputs.extend(receiver_utxos.keys())
    # find payment output and change output
    pay_out = None
    change_out = None
    for o in payment_psbt.unsigned_tx.vout:
        jm_out_fmt = {
            "value": o.nValue,
            "address":
            str(bitcoin.CCoinAddress.from_scriptPubKey(o.scriptPubKey))
        }
        if o.nValue == payment_amt:
            assert pay_out is None
            pay_out = jm_out_fmt
        else:
            assert change_out is None
            change_out = jm_out_fmt

    # we now know there were two outputs and know which is payment.
    # bump payment output with our input:
    outs = [pay_out, change_out]
    our_inputs_val = sum([v["value"] for _, v in receiver_utxos.items()])
    pay_out["value"] += our_inputs_val
    print("we bumped the payment output value by: ", our_inputs_val)
    print("It is now: ", pay_out["value"])
    unsigned_payjoin_tx = bitcoin.make_shuffled_tx(
        payjoin_tx_inputs,
        outs,
        version=payment_psbt.unsigned_tx.nVersion,
        locktime=payment_psbt.unsigned_tx.nLockTime)
    print("we created this unsigned tx: ")
    print(bitcoin.human_readable_transaction(unsigned_payjoin_tx))
    # to create the PSBT we need the spent_outs for each input,
    # in the right order:
    spent_outs = []
    for i, inp in enumerate(unsigned_payjoin_tx.vin):
        input_found = False
        for j, inp2 in enumerate(payment_psbt.unsigned_tx.vin):
            if inp.prevout == inp2.prevout:
                spent_outs.append(payment_psbt.inputs[j].utxo)
                input_found = True
                break
        if input_found:
            continue
        # if we got here this input is ours, we must find
        # it from our original utxo choice list:
        for ru in receiver_utxos.keys():
            if (inp.prevout.hash[::-1], inp.prevout.n) == ru:
                spent_outs.append(
                    wallet_r.witness_utxos_to_psbt_utxos(
                        {ru: receiver_utxos[ru]})[0])
                input_found = True
                break
        # there should be no other inputs:
        assert input_found

    r_payjoin_psbt = wallet_r.create_psbt_from_tx(unsigned_payjoin_tx,
                                                  spent_outs=spent_outs)
    print("Receiver created payjoin PSBT:\n{}".format(
        wallet_r.human_readable_psbt(r_payjoin_psbt)))

    signresultandpsbt, err = wallet_r.sign_psbt(r_payjoin_psbt.serialize(),
                                                with_sign_result=True)
    assert not err, err
    signresult, receiver_signed_psbt = signresultandpsbt
    assert signresult.num_inputs_final == len(receiver_utxos)
    assert not signresult.is_final

    print("Receiver signing successful. Payjoin PSBT is now:\n{}".format(
        wallet_r.human_readable_psbt(receiver_signed_psbt)))

    # *** STEP 3 ***
    # **************

    # take the half-signed PSBT, validate and co-sign:

    signresultandpsbt, err = wallet_s.sign_psbt(
        receiver_signed_psbt.serialize(), with_sign_result=True)
    assert not err, err
    signresult, sender_signed_psbt = signresultandpsbt
    print("Sender's final signed PSBT is:\n{}".format(
        wallet_s.human_readable_psbt(sender_signed_psbt)))
    assert signresult.is_final

    # broadcast the tx
    extracted_tx = sender_signed_psbt.extract_transaction().serialize()
    assert jm_single().bc_interface.pushtx(extracted_tx)
Exemplo n.º 8
0
def test_snicker_e2e(setup_snicker, nw, wallet_structures, mean_amt, sdev_amt,
                     amt, net_transfer):
    """ Test strategy:
    1. create two wallets.
    2. with wallet 1 (Receiver), create a single transaction
    tx1, from mixdepth 0 to 1.
    3. with wallet 2 (Proposer), take pubkey of all inputs from tx1, and use
    them to create snicker proposals to the non-change out of tx1,
    in base64 and place in proposals.txt.
    4. Receiver polls for proposals in the file manually (instead of twisted
    LoopingCall) and processes them.
    5. Check for valid final transaction with broadcast.
    """

    # TODO: Make this test work with native segwit wallets
    wallets = make_wallets(nw,
                           wallet_structures,
                           mean_amt,
                           sdev_amt,
                           wallet_cls=SegwitLegacyWallet)
    for w in wallets.values():
        w['wallet'].sync_wallet(fast=True)
    print(wallets)
    wallet_r = wallets[0]['wallet']
    wallet_p = wallets[1]['wallet']
    # next, create a tx from the receiver wallet
    our_destn_script = wallet_r.get_new_script(
        1, BaseWallet.ADDRESS_TYPE_INTERNAL)
    tx = direct_send(wallet_r,
                     btc.coins_to_satoshi(0.3),
                     0,
                     wallet_r.script_to_addr(our_destn_script),
                     accept_callback=dummy_accept_callback,
                     info_callback=dummy_info_callback,
                     return_transaction=True)

    assert tx, "Failed to spend from receiver wallet"
    print("Parent transaction OK. It was: ")
    print(btc.human_readable_transaction(tx))
    wallet_r.process_new_tx(tx)
    # we must identify the receiver's output we're going to use;
    # it can be destination or change, that's up to the proposer
    # to guess successfully; here we'll just choose index 0.
    txid1 = tx.GetTxid()[::-1]
    txid1_index = 0

    receiver_start_bal = sum(
        [x['value'] for x in wallet_r.get_all_utxos().values()])

    # Now create a proposal for every input index in tx1
    # (version 1 proposals mean we source keys from the/an
    # ancestor transaction)
    propose_keys = []
    for i in range(len(tx.vin)):
        # todo check access to pubkey
        sig, pub = [a for a in iter(tx.wit.vtxinwit[i].scriptWitness)]
        propose_keys.append(pub)
    # the proposer wallet needs to choose a single
    # utxo that is bigger than the output amount of tx1
    prop_m_utxos = wallet_p.get_utxos_by_mixdepth()[0]
    prop_utxo = prop_m_utxos[list(prop_m_utxos)[0]]
    # get the private key for that utxo
    priv = wallet_p.get_key_from_addr(
        wallet_p.script_to_addr(prop_utxo['script']))
    prop_input_amt = prop_utxo['value']
    # construct the arguments for the snicker proposal:
    our_input = list(prop_m_utxos)[0]  # should be (txid, index)
    their_input = (txid1, txid1_index)
    our_input_utxo = btc.CMutableTxOut(prop_utxo['value'], prop_utxo['script'])
    fee_est = estimate_tx_fee(len(tx.vin), 2)
    change_spk = wallet_p.get_new_script(0, BaseWallet.ADDRESS_TYPE_INTERNAL)

    encrypted_proposals = []

    for p in propose_keys:
        # TODO: this can be a loop over all outputs,
        # not just one guessed output, if desired.
        encrypted_proposals.append(
            wallet_p.create_snicker_proposal(our_input,
                                             their_input,
                                             our_input_utxo,
                                             tx.vout[txid1_index],
                                             net_transfer,
                                             fee_est,
                                             priv,
                                             p,
                                             prop_utxo['script'],
                                             change_spk,
                                             version_byte=1) + b"," +
            bintohex(p).encode('utf-8'))
    with open(TEST_PROPOSALS_FILE, "wb") as f:
        f.write(b"\n".join(encrypted_proposals))
    sR = SNICKERReceiver(wallet_r)
    sR.proposals_source = TEST_PROPOSALS_FILE  # avoid clashing with mainnet
    sR.poll_for_proposals()
    assert len(sR.successful_txs) == 1
    wallet_r.process_new_tx(sR.successful_txs[0])
    end_utxos = wallet_r.get_all_utxos()
    print("At end the receiver has these utxos: ", end_utxos)
    receiver_end_bal = sum([x['value'] for x in end_utxos.values()])
    assert receiver_end_bal == receiver_start_bal + net_transfer