示例#1
0
def test_tracker_from_dict_invalid_data(generate_dummy_tracker):
    tracker_dict = generate_dummy_tracker().to_dict()

    for value in [
            "locator", "dispute_txid", "penalty_txid", "penalty_rawtx",
            "user_id"
    ]:
        tracker_dict_copy = deepcopy(tracker_dict)
        tracker_dict_copy[value] = None

        with pytest.raises(ValueError):
            TransactionTracker.from_dict(tracker_dict_copy)
def test_tracker_from_dict_invalid_data():
    tracker_dict = create_dummy_tracker().to_dict()

    for value in ["dispute_txid", "penalty_txid", "penalty_rawtx", "user_id"]:
        tracker_dict_copy = deepcopy(tracker_dict)
        tracker_dict_copy[value] = None

        try:
            TransactionTracker.from_dict(tracker_dict_copy)
            assert False

        except ValueError:
            assert True
示例#3
0
def test_get_all_appointments_responder(api, client, get_all_db_manager):
    # Let's reset the dbs so we can test this clean
    api.watcher.db_manager = get_all_db_manager
    api.watcher.responder.db_manager = get_all_db_manager

    # Check that they are wiped clean
    r = client.get(get_all_appointment_endpoint)
    assert r.status_code == HTTP_OK
    assert len(r.json.get("watcher_appointments")) == 0 and len(r.json.get("responder_trackers")) == 0

    # Add some trackers to the Responder db
    tx_trackers = {}
    for _ in range(10):
        uuid = get_random_value_hex(16)
        tracker_data = {
            "locator": get_random_value_hex(16),
            "dispute_txid": get_random_value_hex(32),
            "penalty_txid": get_random_value_hex(32),
            "penalty_rawtx": get_random_value_hex(250),
            "user_id": get_random_value_hex(16),
        }
        tracker = TransactionTracker.from_dict(tracker_data)
        tx_trackers[uuid] = tracker.to_dict()
        api.watcher.responder.db_manager.store_responder_tracker(uuid, tracker.to_dict())
        api.watcher.db_manager.create_triggered_appointment_flag(uuid)

    # Get all appointments
    r = client.get(get_all_appointment_endpoint)

    # Make sure there is not pending locator in the watcher
    responder_trackers = [v["locator"] for k, v in r.json["responder_trackers"].items()]
    local_locators = [tracker["locator"] for uuid, tracker in tx_trackers.items()]

    assert set(responder_trackers) == set(local_locators)
    assert len(r.json["watcher_appointments"]) == 0
示例#4
0
def test_check_confirmations(responder, monkeypatch):
    # check_confirmations checks, given a list of transaction for a block, what of the known penalty transaction have
    # been confirmed. To test this we need to create a list of transactions and the state of the Responder

    # The responder has a list of unconfirmed transaction, let make that some of them are the ones we've received
    txs = [get_random_value_hex(32) for _ in range(20)]
    unconfirmed_txs = [get_random_value_hex(32) for _ in range(10)]
    txs_subset = random.sample(txs, k=10)
    unconfirmed_txs.extend(txs_subset)

    # We also need to add them to the tx_tracker_map since they would be there in normal conditions
    tx_tracker_map = {
        txid: TransactionTracker(txid[:LOCATOR_LEN_HEX], txid, None, None,
                                 None)
        for txid in unconfirmed_txs
    }

    # Mock the structures
    monkeypatch.setattr(responder, "unconfirmed_txs", unconfirmed_txs)
    monkeypatch.setattr(responder, "tx_tracker_map", tx_tracker_map)

    # Let's make sure that there are no txs with missed confirmations yet
    assert len(responder.missed_confirmations) == 0

    # After checking confirmations the txs in txs_subset should be confirmed (not part of unconfirmed_txs anymore)
    # and the rest should have a missing confirmation
    responder.check_confirmations(txs)

    for tx in txs_subset:
        assert tx not in responder.unconfirmed_txs

    for tx in responder.unconfirmed_txs:
        assert responder.missed_confirmations[tx] == 1
示例#5
0
def test_check_confirmations(db_manager, carrier, block_processor):
    responder = Responder(db_manager, carrier, block_processor)
    chain_monitor = ChainMonitor(Queue(), responder.block_queue,
                                 block_processor, bitcoind_feed_params)
    chain_monitor.monitor_chain()

    # check_confirmations checks, given a list of transaction for a block, what of the known penalty transaction have
    # been confirmed. To test this we need to create a list of transactions and the state of the responder
    txs = [get_random_value_hex(32) for _ in range(20)]

    # The responder has a list of unconfirmed transaction, let make that some of them are the ones we've received
    responder.unconfirmed_txs = [get_random_value_hex(32) for _ in range(10)]
    txs_subset = random.sample(txs, k=10)
    responder.unconfirmed_txs.extend(txs_subset)

    # We also need to add them to the tx_tracker_map since they would be there in normal conditions
    responder.tx_tracker_map = {
        txid: TransactionTracker(txid[:LOCATOR_LEN_HEX], txid, None, None,
                                 None)
        for txid in responder.unconfirmed_txs
    }

    # Let's make sure that there are no txs with missed confirmations yet
    assert len(responder.missed_confirmations) == 0

    responder.check_confirmations(txs)

    # After checking confirmations the txs in txs_subset should be confirmed (not part of unconfirmed_txs anymore)
    # and the rest should have a missing confirmation
    for tx in txs_subset:
        assert tx not in responder.unconfirmed_txs

    for tx in responder.unconfirmed_txs:
        assert responder.missed_confirmations[tx] == 1
示例#6
0
def test_get_appointment_in_responder(api, client, appointment):
    # Mock the appointment in the Responder
    tracker_data = {
        "locator": appointment.locator,
        "dispute_txid": get_random_value_hex(32),
        "penalty_txid": get_random_value_hex(32),
        "penalty_rawtx": get_random_value_hex(250),
        "user_id": get_random_value_hex(16),
    }
    tx_tracker = TransactionTracker.from_dict(tracker_data)

    uuid = hash_160("{}{}".format(appointment.locator, user_id))
    api.watcher.db_manager.create_triggered_appointment_flag(uuid)
    api.watcher.responder.db_manager.store_responder_tracker(uuid, tx_tracker.to_dict())

    # Request back the data
    message = "get appointment {}".format(appointment.locator)
    signature = Cryptographer.sign(message.encode("utf-8"), user_sk)
    data = {"locator": appointment.locator, "signature": signature}

    # Next we can request it
    r = client.post(get_appointment_endpoint, json=data)
    assert r.status_code == HTTP_OK

    # Check that the appointment is on the Responder
    assert r.json.get("status") == "dispute_responded"

    # Check the the sent appointment matches the received one
    assert tx_tracker.locator == r.json.get("locator")
    assert tx_tracker.dispute_txid == r.json.get("appointment").get("dispute_txid")
    assert tx_tracker.penalty_txid == r.json.get("appointment").get("penalty_txid")
    assert tx_tracker.penalty_rawtx == r.json.get("appointment").get("penalty_rawtx")
示例#7
0
    def build_trackers(tracker_data):
        """
        Builds a tracker dictionary (``uuid:TransactionTracker``) and a tx_tracker_map (``penalty_txid:uuid``) given
        a dictionary of trackers from the database.

        Args:
            tracker_data (:obj:`dict`): a dictionary of dictionaries representing all the
                :mod:`Responder <teos.responder.Responder>` trackers stored in the database.
                The structure is as follows:

                    ``{uuid: {locator: str, dispute_txid: str, ...}, uuid: {locator:...}}``

        Returns:
            :obj:`tuple`: A tuple with two dictionaries. ``trackers`` containing the trackers' information in
            :obj:`TransactionTracker <teos.responder.TransactionTracker>` objects and a ``tx_tracker_map`` containing
            the map of trackers (``penalty_txid: uuid``).

        """

        trackers = {}
        tx_tracker_map = {}

        for uuid, data in tracker_data.items():
            tracker = TransactionTracker.from_dict(data)
            trackers[uuid] = tracker.get_summary()

            if tracker.penalty_txid in tx_tracker_map:
                tx_tracker_map[tracker.penalty_txid].append(uuid)

            else:
                tx_tracker_map[tracker.penalty_txid] = [uuid]

        return trackers, tx_tracker_map
示例#8
0
def set_up_trackers(db_manager, total_trackers):
    trackers = dict()
    tx_tracker_map = dict()

    for i in range(total_trackers):
        uuid = uuid4().hex

        # We use the same txid for penalty and dispute here, it shouldn't matter
        penalty_txid = get_random_value_hex(32)
        dispute_txid = get_random_value_hex(32)
        locator = dispute_txid[:LOCATOR_LEN_HEX]

        # Appointment data
        appointment = Appointment(locator, None, None)

        # Store the data in the database and create a flag
        db_manager.store_watcher_appointment(uuid, appointment.to_dict())
        db_manager.create_triggered_appointment_flag(uuid)

        # Assign both penalty_txid and dispute_txid the same id (it shouldn't matter)
        tracker = TransactionTracker(locator, dispute_txid, penalty_txid, None,
                                     None)
        trackers[uuid] = {
            "locator": tracker.locator,
            "penalty_txid": tracker.penalty_txid
        }
        tx_tracker_map[penalty_txid] = [uuid]

        db_manager.store_responder_tracker(uuid, tracker.to_dict())

        # Each penalty_txid can have more than one uuid assigned to it.
        if i % 2:
            uuid = uuid4().hex

            trackers[uuid] = {
                "locator": tracker.locator,
                "penalty_txid": tracker.penalty_txid
            }
            tx_tracker_map[penalty_txid].append(uuid)

            db_manager.store_responder_tracker(uuid, tracker.to_dict())

            # Add them to the Watcher's db too
            db_manager.store_watcher_appointment(uuid, appointment.to_dict())
            db_manager.create_triggered_appointment_flag(uuid)

    return trackers, tx_tracker_map
示例#9
0
def test_rebroadcast(db_manager, carrier, block_processor):
    responder = Responder(db_manager, carrier, block_processor)
    chain_monitor = ChainMonitor(Queue(), responder.block_queue,
                                 block_processor, bitcoind_feed_params)
    chain_monitor.monitor_chain()

    txs_to_rebroadcast = []

    # Rebroadcast calls add_response with retry=True. The tracker data is already in trackers.
    for i in range(20):
        uuid = uuid4().hex
        locator, dispute_txid, penalty_txid, penalty_rawtx, appointment_end = create_dummy_tracker_data(
            penalty_rawtx=create_dummy_transaction().hex())

        tracker = TransactionTracker(locator, dispute_txid, penalty_txid,
                                     penalty_rawtx, appointment_end)

        responder.trackers[uuid] = {
            "locator": locator,
            "penalty_txid": penalty_txid,
            "appointment_end": appointment_end,
        }

        # We need to add it to the db too
        responder.db_manager.create_triggered_appointment_flag(uuid)
        responder.db_manager.store_responder_tracker(uuid, tracker.to_json())

        responder.tx_tracker_map[penalty_txid] = [uuid]
        responder.unconfirmed_txs.append(penalty_txid)

        # Let's add some of the txs in the rebroadcast list
        if (i % 2) == 0:
            txs_to_rebroadcast.append(penalty_txid)

    # The block_hash passed to rebroadcast does not matter much now. It will in the future to deal with errors
    receipts = responder.rebroadcast(txs_to_rebroadcast)

    # All txs should have been delivered and the missed confirmation reset
    for txid, receipt in receipts:
        # Sanity check
        assert txid in txs_to_rebroadcast

        assert receipt.delivered is True
        assert responder.missed_confirmations[txid] == 0
示例#10
0
def test_tracker_init(run_bitcoind):
    locator, dispute_txid, penalty_txid, penalty_rawtx, appointment_end = create_dummy_tracker_data(
    )
    tracker = TransactionTracker(locator, dispute_txid, penalty_txid,
                                 penalty_rawtx, appointment_end)

    assert (tracker.dispute_txid == dispute_txid
            and tracker.penalty_txid == penalty_txid
            and tracker.penalty_rawtx == penalty_rawtx
            and tracker.appointment_end == appointment_end)
def test_tracker_init(run_bitcoind):
    locator, dispute_txid, penalty_txid, penalty_rawtx, user_id = create_dummy_tracker_data(
    )
    tracker = TransactionTracker(locator, dispute_txid, penalty_txid,
                                 penalty_rawtx, user_id)

    assert (tracker.locator == locator and tracker.dispute_txid == dispute_txid
            and tracker.penalty_txid == penalty_txid
            and tracker.penalty_rawtx == penalty_rawtx
            and tracker.user_id == user_id)
示例#12
0
    def _generate_dummy_tracker():
        tracker_data = dict(
            locator=get_random_value_hex(16),
            dispute_txid=get_random_value_hex(32),
            penalty_txid=get_random_value_hex(32),
            penalty_rawtx=get_random_value_hex(150),
            user_id="02" + get_random_value_hex(32),
        )

        return TransactionTracker.from_dict(tracker_data)
示例#13
0
def set_up_trackers(db_manager, total_trackers):
    trackers = dict()
    tx_tracker_map = dict()

    for i in range(total_trackers):
        uuid = uuid4().hex

        # We use the same txid for penalty and dispute here, it shouldn't matter
        penalty_txid = get_random_value_hex(32)
        dispute_txid = get_random_value_hex(32)
        locator = dispute_txid[:LOCATOR_LEN_HEX]

        # Assign both penalty_txid and dispute_txid the same id (it shouldn't matter)
        tracker = TransactionTracker(locator, dispute_txid, penalty_txid, None,
                                     None)
        trackers[uuid] = {
            "locator": tracker.locator,
            "penalty_txid": tracker.penalty_txid
        }
        tx_tracker_map[penalty_txid] = [uuid]

        db_manager.store_responder_tracker(uuid, tracker.to_json())
        db_manager.create_append_locator_map(tracker.locator, uuid)

        # Each penalty_txid can have more than one uuid assigned to it.
        if i % 2:
            uuid = uuid4().hex

            trackers[uuid] = {
                "locator": tracker.locator,
                "penalty_txid": tracker.penalty_txid
            }
            tx_tracker_map[penalty_txid].append(uuid)

            db_manager.store_responder_tracker(uuid, tracker.to_json())
            db_manager.create_append_locator_map(tracker.locator, uuid)

    return trackers, tx_tracker_map
示例#14
0
def test_tracker_init():
    locator = get_random_value_hex(32)
    dispute_txid = get_random_value_hex(32)
    penalty_txid = get_random_value_hex(32)
    penalty_tx = get_random_value_hex(200)
    user_id = get_random_value_hex(16)

    tracker = TransactionTracker(locator, dispute_txid, penalty_txid,
                                 penalty_tx, user_id)

    assert (tracker.locator == locator and tracker.dispute_txid == dispute_txid
            and tracker.penalty_txid == penalty_txid
            and tracker.penalty_rawtx == penalty_tx
            and tracker.user_id == user_id)
示例#15
0
def test_tracker_init():
    # Simple test to check that creating a Tracker works
    locator = get_random_value_hex(32)
    dispute_txid = get_random_value_hex(32)
    penalty_txid = get_random_value_hex(32)
    penalty_tx = get_random_value_hex(200)
    user_id = get_random_value_hex(16)

    tracker = TransactionTracker(locator, dispute_txid, penalty_txid,
                                 penalty_tx, user_id)

    assert (tracker.locator == locator and tracker.dispute_txid == dispute_txid
            and tracker.penalty_txid == penalty_txid
            and tracker.penalty_rawtx == penalty_tx
            and tracker.user_id == user_id)
示例#16
0
def generate_dummy_tracker():
    dispute_txid = get_random_value_hex(32)
    penalty_txid = get_random_value_hex(32)
    penalty_rawtx = get_random_value_hex(100)
    locator = dispute_txid[:LOCATOR_LEN_HEX]

    tracker_data = dict(
        locator=locator,
        dispute_txid=dispute_txid,
        penalty_txid=penalty_txid,
        penalty_rawtx=penalty_rawtx,
        appointment_end=100,
    )

    return TransactionTracker.from_dict(tracker_data)
示例#17
0
    def _generate_dummy_tracker(commitment_tx=None):
        if not commitment_tx:
            commitment_tx = create_commitment_tx()
        decoded_commitment_tx = bitcoin_cli.decoderawtransaction(commitment_tx)
        penalty_tx = create_penalty_tx(decoded_commitment_tx)
        locator = decoded_commitment_tx.get("txid")[:LOCATOR_LEN_HEX]

        tracker_data = dict(
            locator=locator,
            dispute_txid=bitcoin_cli.decoderawtransaction(commitment_tx).get(
                "txid"),
            penalty_txid=bitcoin_cli.decoderawtransaction(penalty_tx).get(
                "txid"),
            penalty_rawtx=penalty_tx,
            user_id="02" + get_random_value_hex(32),
        )

        return TransactionTracker.from_dict(tracker_data)
示例#18
0
def create_dummy_tracker(random_txid=False, penalty_rawtx=None):
    locator, dispute_txid, penalty_txid, penalty_rawtx, appointment_end = create_dummy_tracker_data(
        random_txid, penalty_rawtx)
    return TransactionTracker(locator, dispute_txid, penalty_txid,
                              penalty_rawtx, appointment_end)
示例#19
0
def test_tracker_from_dict():
    tracker_dict = create_dummy_tracker().to_dict()
    new_tracker = TransactionTracker.from_dict(tracker_dict)

    assert tracker_dict == new_tracker.to_dict()
示例#20
0
def test_tracker_from_dict(generate_dummy_tracker):
    # Check that a tracker can be created from a dictionary
    tracker_dict = generate_dummy_tracker().to_dict()
    new_tracker = TransactionTracker.from_dict(tracker_dict)

    assert tracker_dict == new_tracker.to_dict()