def test_unrelated_tx():
    ###transaction that has nothing to do with our wallet
    dummy_spk, containing_block_height, dummy_tx = create_dummy_funding_tx(
        confirmations=0)
    our_dummy_spk = create_dummy_spk()

    rpc = DummyJsonRpc([dummy_tx], [], {dummy_tx["blockhash"]:
        containing_block_height})
    txmonitor = TransactionMonitor(rpc, deterministic_wallets, debugf, logf)
    assert txmonitor.build_address_history([our_dummy_spk])
    assert len(txmonitor.address_history) == 1
    assert len(txmonitor.get_electrum_history(script_to_scripthash(
        our_dummy_spk))) == 0
def test_single_tx():
    ###single confirmed tx in wallet belonging to us, address history built
    dummy_spk, containing_block_height, dummy_tx = create_dummy_funding_tx()

    rpc = DummyJsonRpc([dummy_tx], [],
                       {dummy_tx["blockhash"]: containing_block_height})
    txmonitor = TransactionMonitor(rpc, deterministic_wallets, debugf, logf)
    assert txmonitor.build_address_history([dummy_spk])
    assert len(txmonitor.address_history) == 1
    assert_address_history_tx(txmonitor.address_history,
                              spk=dummy_spk,
                              height=containing_block_height,
                              txid=dummy_tx["txid"],
                              subscribed=False)
def test_conflicted_tx():
    ###conflicted transaction should get rejected
    dummy_spk, containing_block_height, dummy_tx = create_dummy_funding_tx(
        confirmations=-1)

    rpc = DummyJsonRpc([dummy_tx], [], {})
    txmonitor = TransactionMonitor(rpc, deterministic_wallets, debugf, logf)
    assert txmonitor.build_address_history([dummy_spk])
    assert len(txmonitor.address_history) == 1
    assert len(txmonitor.get_electrum_history(script_to_scripthash(
        dummy_spk))) == 0  #shouldnt show up after build history b/c conflicted
    rpc.add_transaction(dummy_tx)
    assert len(list(txmonitor.check_for_updated_txes())) == 0
    assert len(txmonitor.get_electrum_history(
        script_to_scripthash(dummy_spk))) == 0  #incoming tx is not added too
def test_from_address():
    ###transaction spending FROM one of our addresses
    dummy_spk1, containing_block_height1, input_tx = create_dummy_funding_tx()
    dummy_spk2, containing_block_height2, spending_tx = create_dummy_funding_tx(
        input_txid=input_tx["txid"])

    rpc = DummyJsonRpc(
        [input_tx, spending_tx], [], {
            input_tx["blockhash"]: containing_block_height1,
            spending_tx["blockhash"]: containing_block_height2
        })
    txmonitor = TransactionMonitor(rpc, deterministic_wallets, debugf, logf)
    assert txmonitor.build_address_history([dummy_spk1])
    sh = script_to_scripthash(dummy_spk1)
    assert len(txmonitor.get_electrum_history(sh)) == 2
def test_tx_within_wallet():
    ###transaction from one address to the other, both addresses in wallet
    dummy_spk1, containing_block_height1, dummy_tx1 = create_dummy_funding_tx()
    dummy_spk2, containing_block_height2, dummy_tx2 = create_dummy_funding_tx(
        input_txid=dummy_tx1["txid"])

    rpc = DummyJsonRpc([dummy_tx1, dummy_tx2], [],
        {dummy_tx1["blockhash"]: containing_block_height1,
        dummy_tx2["blockhash"]: containing_block_height2})
    txmonitor = TransactionMonitor(rpc, deterministic_wallets, debugf, logf)
    assert txmonitor.build_address_history([dummy_spk1, dummy_spk2])
    assert len(txmonitor.get_electrum_history(script_to_scripthash(
        dummy_spk1))) == 2
    assert len(txmonitor.get_electrum_history(script_to_scripthash(
        dummy_spk2))) == 1
def test_address_reuse():
    ###transaction which arrives to an address which already has a tx on it
    dummy_spk1, containing_block_height1, dummy_tx1 = create_dummy_funding_tx()
    dummy_spk2, containing_block_height2, dummy_tx2 = create_dummy_funding_tx(
        output_spk=dummy_spk1)

    rpc = DummyJsonRpc([dummy_tx1], [], {dummy_tx1["blockhash"]:
        containing_block_height1, dummy_tx2["blockhash"]:
        containing_block_height2})
    txmonitor = TransactionMonitor(rpc, deterministic_wallets, debugf, logf)
    assert txmonitor.build_address_history([dummy_spk1])
    sh = script_to_scripthash(dummy_spk1)
    assert len(txmonitor.get_electrum_history(sh)) == 1
    rpc.add_transaction(dummy_tx2)
    assert len(txmonitor.get_electrum_history(sh)) == 1
    txmonitor.check_for_updated_txes()
    assert len(txmonitor.get_electrum_history(sh)) == 2
def test_two_txes():
    ###two confirmed txes in wallet belonging to us, addr history built
    dummy_spk1, containing_block_height1, dummy_tx1 = create_dummy_funding_tx()
    dummy_spk2, containing_block_height2, dummy_tx2 = create_dummy_funding_tx()

    rpc = DummyJsonRpc([dummy_tx1, dummy_tx2], [],
        {dummy_tx1["blockhash"]: containing_block_height1,
        dummy_tx2["blockhash"]: containing_block_height2})
    txmonitor = TransactionMonitor(rpc, deterministic_wallets, debugf, logf)
    assert txmonitor.build_address_history([dummy_spk1, dummy_spk2])
    assert len(txmonitor.address_history) == 2
    assert_address_history_tx(txmonitor.address_history, spk=dummy_spk1,
        height=containing_block_height1, txid=dummy_tx1["txid"],
        subscribed=False)
    assert_address_history_tx(txmonitor.address_history, spk=dummy_spk2,
        height=containing_block_height2, txid=dummy_tx2["txid"],
        subscribed=False)
def test_reorg_censor_tx():
    #confirmed tx gets reorgd out and becomes unconfirmed
    dummy_spk1, containing_block_height1, dummy_tx1 = create_dummy_funding_tx()

    rpc = DummyJsonRpc([dummy_tx1], [dummy_tx1["vin"][0]],
        {dummy_tx1["blockhash"]: containing_block_height1})
    txmonitor = TransactionMonitor(rpc, deterministic_wallets, debugf, logf)
    assert txmonitor.build_address_history([dummy_spk1])
    assert len(txmonitor.address_history) == 1
    sh = script_to_scripthash(dummy_spk1)
    assert len(txmonitor.get_electrum_history(sh)) == 1
    assert_address_history_tx(txmonitor.address_history, spk=dummy_spk1,
        height=containing_block_height1, txid=dummy_tx1["txid"], subscribed=False)
    #blocks appear which reorg out the tx, making it unconfirmed
    dummy_tx1["confirmations"] = 0
    assert len(list(txmonitor.check_for_updated_txes())) == 0
    assert len(txmonitor.get_electrum_history(sh)) == 1
    assert_address_history_tx(txmonitor.address_history, spk=dummy_spk1,
        height=0, txid=dummy_tx1["txid"], subscribed=False)
def test_non_subscribed_confirmation():
    ###one unconfirmed tx in wallet belonging to us, with confirmed inputs,
    ### addr history built, then tx confirms, not subscribed to address
    dummy_spk, containing_block_height, dummy_tx = create_dummy_funding_tx(
        confirmations=0)

    rpc = DummyJsonRpc([dummy_tx], [dummy_tx["vin"][0]],
        {dummy_tx["blockhash"]: containing_block_height})
    txmonitor = TransactionMonitor(rpc, deterministic_wallets, debugf, logf)
    assert txmonitor.build_address_history([dummy_spk])
    assert len(txmonitor.address_history) == 1
    assert_address_history_tx(txmonitor.address_history, spk=dummy_spk,
        height=0, txid=dummy_tx["txid"], subscribed=False)
    assert len(list(txmonitor.check_for_updated_txes())) == 0
    dummy_tx["confirmations"] = 1 #tx confirms
    #not subscribed so still only returns an empty list
    assert len(list(txmonitor.check_for_updated_txes())) == 0
    assert_address_history_tx(txmonitor.address_history, spk=dummy_spk,
        height=containing_block_height, txid=dummy_tx["txid"], subscribed=False)
def test_duplicate_txid():
    ###two txes with the same txid, built history
    dummy_spk, containing_block_height1, dummy_tx1 = create_dummy_funding_tx()
    dummy_spk, containing_block_height2, dummy_tx2 = create_dummy_funding_tx(
        output_spk=dummy_spk)
    dummy_spk, containing_block_height3, dummy_tx3 = create_dummy_funding_tx(
        output_spk=dummy_spk)
    dummy_tx2["txid"] = dummy_tx1["txid"]
    dummy_tx3["txid"] = dummy_tx1["txid"]
    sh = script_to_scripthash(dummy_spk)
    rpc = DummyJsonRpc([dummy_tx1, dummy_tx2], [], {dummy_tx1["blockhash"]:
        containing_block_height1, dummy_tx2["blockhash"]: containing_block_height2, dummy_tx3["blockhash"]: containing_block_height3})
    txmonitor = TransactionMonitor(rpc, deterministic_wallets, debugf, logf)
    assert txmonitor.build_address_history([dummy_spk])
    assert len(txmonitor.get_electrum_history(sh)) == 1
    txmonitor.subscribe_address(sh)
    assert txmonitor.get_electrum_history(sh)[0]["tx_hash"] == dummy_tx1["txid"]
    rpc.add_transaction(dummy_tx3)
    assert len(list(txmonitor.check_for_updated_txes())) == 1
    assert len(txmonitor.get_electrum_history(sh)) == 1
    assert txmonitor.get_electrum_history(sh)[0]["tx_hash"] == dummy_tx1["txid"]
def test_reorg_different_block():
    #confirmed tx gets reorged into another block with a different height
    dummy_spk1, containing_block_height1, dummy_tx1 = create_dummy_funding_tx()
    dummy_spk2, containing_block_height2, dummy_tx2 = create_dummy_funding_tx()

    rpc = DummyJsonRpc([dummy_tx1], [],
        {dummy_tx1["blockhash"]: containing_block_height1,
        dummy_tx2["blockhash"]: containing_block_height2})
    txmonitor = TransactionMonitor(rpc, deterministic_wallets, debugf, logf)
    assert txmonitor.build_address_history([dummy_spk1])
    assert len(txmonitor.address_history) == 1
    sh = script_to_scripthash(dummy_spk1)
    assert len(txmonitor.get_electrum_history(sh)) == 1
    assert_address_history_tx(txmonitor.address_history, spk=dummy_spk1,
        height=containing_block_height1, txid=dummy_tx1["txid"], subscribed=False)

    #tx gets reorged into another block (so still confirmed)
    dummy_tx1["blockhash"] = dummy_tx2["blockhash"]
    assert len(list(txmonitor.check_for_updated_txes())) == 0
    assert len(txmonitor.get_electrum_history(sh)) == 1
    assert_address_history_tx(txmonitor.address_history, spk=dummy_spk1,
        height=containing_block_height2, txid=dummy_tx1["txid"],
        subscribed=False)
def test_double_spend():
    ###an unconfirmed tx being broadcast, another conflicting tx being
    ### confirmed, the first tx gets conflicted status

    dummy_spk, containing_block_height1, dummy_tx1 = create_dummy_funding_tx(
        confirmations=0)
    dummy_spk_, containing_block_height2, dummy_tx2 = create_dummy_funding_tx(
        confirmations=0, input_txid=dummy_tx1["vin"][0], output_spk=dummy_spk)
    #two unconfirmed txes spending the same input, so they are in conflict

    rpc = DummyJsonRpc(
        [dummy_tx1], [dummy_tx1["vin"][0]], {
            dummy_tx1["blockhash"]: containing_block_height1,
            dummy_tx2["blockhash"]: containing_block_height2
        })
    txmonitor = TransactionMonitor(rpc, deterministic_wallets, debugf, logf)
    assert txmonitor.build_address_history([dummy_spk])
    assert len(txmonitor.address_history) == 1
    sh = script_to_scripthash(dummy_spk)
    assert len(txmonitor.get_electrum_history(sh)) == 1
    assert_address_history_tx(txmonitor.address_history,
                              spk=dummy_spk,
                              height=0,
                              txid=dummy_tx1["txid"],
                              subscribed=False)
    # a conflicting transaction confirms
    rpc.add_transaction(dummy_tx2)
    dummy_tx1["confirmations"] = -1
    dummy_tx2["confirmations"] = 1
    assert len(list(txmonitor.check_for_updated_txes())) == 0
    assert len(txmonitor.get_electrum_history(sh)) == 1
    assert_address_history_tx(txmonitor.address_history,
                              spk=dummy_spk,
                              height=containing_block_height2,
                              txid=dummy_tx2["txid"],
                              subscribed=False)