Ejemplo n.º 1
0
def test_register_no_signature():
    # Simulate a register response with a wrong signature
    slots = 100
    expiry = CURRENT_HEIGHT + 4320
    response = {"available_slots": slots, "subscription_expiry": expiry}
    responses.add(responses.POST, register_endpoint, json=response, status=200)

    with pytest.raises(TowerResponseError,
                       match="does not contain the signature"):
        teos_client.register(dummy_user_id, dummy_teos_id, teos_url)
Ejemplo n.º 2
0
def test_get_users(teosd, rpc_client):
    _, teos_id = teosd

    # Create a fresh user
    tmp_user_id = Cryptographer.get_compressed_pk(Cryptographer.generate_key().public_key)

    users = json.loads(rpc_client.get_users())
    assert tmp_user_id not in users

    # Register the fresh user
    teos_client.register(tmp_user_id, teos_id, teos_base_endpoint)

    users = json.loads(rpc_client.get_users())
    assert tmp_user_id in users
Ejemplo n.º 3
0
def test_register():
    # Simulate a register response
    slots = 100
    expiry = CURRENT_HEIGHT + 4320
    signature = Cryptographer.sign(
        receipts.create_registration_receipt(dummy_user_id, slots, expiry),
        dummy_teos_sk)
    response = {
        "available_slots": slots,
        "subscription_expiry": expiry,
        "subscription_signature": signature
    }
    responses.add(responses.POST, register_endpoint, json=response, status=200)
    teos_client.register(dummy_user_id, dummy_teos_id, teos_url)
Ejemplo n.º 4
0
def test_register_wrong_signature():
    # Simulate a register response with a wrong signature
    slots = 100
    expiry = CURRENT_HEIGHT + 4320
    signature = Cryptographer.sign(
        receipts.create_registration_receipt(dummy_user_id, slots, expiry),
        another_sk)
    response = {
        "available_slots": slots,
        "subscription_expiry": expiry,
        "subscription_signature": signature
    }
    responses.add(responses.POST, register_endpoint, json=response, status=200)

    with pytest.raises(TowerResponseError, match="signature is invalid"):
        teos_client.register(dummy_user_id, dummy_teos_id, teos_url)
Ejemplo n.º 5
0
def test_commands_registered(teosd):
    global appointments_in_watcher, available_slots
    _, teos_id = teosd

    # Test registering and trying again
    available_slots, subscription_expiry = teos_client.register(user_id, teos_id, teos_base_endpoint)

    # Add appointment
    commitment_tx, commitment_txid, penalty_tx = create_txs()
    appointment_data = build_appointment_data(commitment_txid, penalty_tx)

    appointment = teos_client.create_appointment(appointment_data)
    add_appointment(teos_id, appointment)

    # Get appointment
    r = get_appointment_info(teos_id, appointment_data.get("locator"))
    assert r.get("locator") == appointment.locator
    assert r.get("appointment") == appointment.to_dict()
    appointments_in_watcher += 1
    available_slots -= 1

    # Get subscription info
    r = get_subscription_info(teos_id)
    assert r.get("appointments")[0] == appointment.locator
    # Subtract 1 since we just added an appointment
    assert r.get("available_slots") == available_slots
    assert r.get("subscription_expiry") == subscription_expiry
Ejemplo n.º 6
0
def test_get_all_appointments(teosd, rpc_client):
    _, teos_id = teosd

    # Check that there is no appointment, so far
    all_appointments = json.loads(rpc_client.get_all_appointments())
    watching = all_appointments.get("watcher_appointments")
    responding = all_appointments.get("responder_trackers")
    assert len(watching) == 0 and len(responding) == 0

    # Register a user
    teos_client.register(user_id, teos_id, teos_base_endpoint)

    # After that we can build an appointment and send it to the tower
    commitment_tx, commitment_txid, penalty_tx = create_txs()
    appointment_data = build_appointment_data(commitment_txid, penalty_tx)
    appointment = teos_client.create_appointment(appointment_data)
    add_appointment(teos_id, appointment)

    # Now there should now be one appointment in the watcher
    all_appointments = json.loads(rpc_client.get_all_appointments())
    watching = all_appointments.get("watcher_appointments")
    responding = all_appointments.get("responder_trackers")
    assert len(watching) == 1 and len(responding) == 0

    # Trigger a breach and check again; now the appointment should be in the responder
    generate_block_with_transactions(commitment_tx)
    sleep(1)

    all_appointments = json.loads(rpc_client.get_all_appointments())
    watching = all_appointments.get("watcher_appointments")
    responding = all_appointments.get("responder_trackers")
    assert len(watching) == 0 and len(responding) == 1

    # Now let's mine some blocks so the appointment reaches its end. We need 100 + EXPIRY_DELTA -1
    generate_blocks(100 + config.get("EXPIRY_DELTA"))
    sleep(1)

    # Now the appointment should not be in the tower, back to 0
    all_appointments = json.loads(rpc_client.get_all_appointments())
    watching = all_appointments.get("watcher_appointments")
    responding = all_appointments.get("responder_trackers")
    assert len(watching) == 0 and len(responding) == 0
Ejemplo n.º 7
0
def test_two_appointment_same_locator_different_penalty_different_users(teosd):
    _, teos_id = teosd

    # This tests sending an appointment with two valid transaction with the same locator from different users
    commitment_tx, commitment_txid, penalty_tx1 = create_txs()

    # We need to create a second penalty spending from the same commitment
    decoded_commitment_tx = bitcoin_cli.decoderawtransaction(commitment_tx)
    new_addr = bitcoin_cli.getnewaddress()
    penalty_tx2 = create_penalty_tx(decoded_commitment_tx, new_addr)

    appointment1_data = build_appointment_data(commitment_txid, penalty_tx1)
    appointment2_data = build_appointment_data(commitment_txid, penalty_tx2)
    locator = compute_locator(commitment_txid)

    # tmp keys for a different user
    tmp_user_sk = PrivateKey()
    tmp_user_id = Cryptographer.get_compressed_pk(tmp_user_sk.public_key)
    teos_client.register(tmp_user_id, teos_id, teos_base_endpoint)

    appointment_1 = teos_client.create_appointment(appointment1_data)
    add_appointment(teos_id, appointment_1)
    appointment_2 = teos_client.create_appointment(appointment2_data)
    add_appointment(teos_id, appointment_2, sk=tmp_user_sk)

    # Broadcast the commitment transaction and mine a block
    generate_block_with_transactions(commitment_tx)

    # One of the transactions must have made it to the Responder while the other must have been dropped for
    # double-spending. That means that one of the responses from the tower should fail
    appointment_info = None
    with pytest.raises(TowerResponseError):
        appointment_info = get_appointment_info(teos_id, locator)
        appointment2_info = get_appointment_info(teos_id, locator, sk=tmp_user_sk)

    if appointment_info is None:
        appointment_info = appointment2_info
        appointment1_data = appointment2_data

    assert appointment_info.get("status") == AppointmentStatus.DISPUTE_RESPONDED
    assert appointment_info.get("locator") == appointment1_data.get("locator")
    assert appointment_info.get("appointment").get("penalty_tx") == appointment1_data.get("penalty_tx")
Ejemplo n.º 8
0
def test_get_user(teosd, rpc_client):
    _, teos_id = teosd

    # Register a user
    available_slots, subscription_expiry = teos_client.register(user_id, teos_id, teos_base_endpoint)

    # Get back its info
    user = json.loads(rpc_client.get_user(user_id))

    assert set(user.keys()) == set(["appointments", "available_slots", "subscription_expiry"])
    assert user["available_slots"] == available_slots
    assert user["subscription_expiry"] == subscription_expiry
Ejemplo n.º 9
0
def test_register_with_connection_error():
    # We don't mock any url to simulate a connection error
    with pytest.raises(ConnectionError):
        teos_client.register(dummy_user_id, dummy_teos_id, teos_url)

    # Should also fail with missing or unknown protocol, with a more specific error message
    with pytest.raises(ConnectionError, match="Invalid URL"):
        teos_client.register(dummy_user_id, dummy_teos_id, "//teos.watch")
    with pytest.raises(ConnectionError, match="Invalid URL"):
        teos_client.register(dummy_user_id, dummy_teos_id,
                             "nonExistingProtocol://teos.watch")
Ejemplo n.º 10
0
def test_register_with_invalid_user_id():
    # Simulate a register response
    with pytest.raises(InvalidParameter):
        teos_client.register("invalid_user_id", dummy_teos_id, teos_url)
Ejemplo n.º 11
0
def test_appointment_life_cycle(teosd):
    global appointments_in_watcher, appointments_in_responder, available_slots, subscription_expiry

    _, teos_id = teosd

    # First of all we need to register
    available_slots, subscription_expiry = teos_client.register(user_id, teos_id, teos_base_endpoint)

    # After that we can build an appointment and send it to the tower
    commitment_tx, commitment_txid, penalty_tx = create_txs()
    appointment_data = build_appointment_data(commitment_txid, penalty_tx)
    locator = compute_locator(commitment_txid)
    appointment = teos_client.create_appointment(appointment_data)
    add_appointment(teos_id, appointment)
    appointments_in_watcher += 1

    # Get the information from the tower to check that it matches
    appointment_info = get_appointment_info(teos_id, locator)
    assert appointment_info.get("status") == AppointmentStatus.BEING_WATCHED
    assert appointment_info.get("locator") == locator
    assert appointment_info.get("appointment") == appointment.to_dict()

    rpc_client = RPCClient(config.get("RPC_BIND"), config.get("RPC_PORT"))

    # Check also the get_all_appointments endpoint
    all_appointments = json.loads(rpc_client.get_all_appointments())
    watching = all_appointments.get("watcher_appointments")
    responding = all_appointments.get("responder_trackers")
    assert len(watching) == appointments_in_watcher and len(responding) == 0

    # Trigger a breach and check again
    generate_block_with_transactions(commitment_tx)
    appointment_info = get_appointment_info(teos_id, locator)
    assert appointment_info.get("status") == AppointmentStatus.DISPUTE_RESPONDED
    assert appointment_info.get("locator") == locator
    appointments_in_watcher -= 1
    appointments_in_responder += 1

    all_appointments = json.loads(rpc_client.get_all_appointments())
    watching = all_appointments.get("watcher_appointments")
    responding = all_appointments.get("responder_trackers")
    assert len(watching) == appointments_in_watcher and len(responding) == appointments_in_responder

    # It can be also checked by ensuring that the penalty transaction made it to the network
    penalty_tx_id = bitcoin_cli.decoderawtransaction(penalty_tx).get("txid")

    try:
        bitcoin_cli.getrawtransaction(penalty_tx_id)
        assert True

    except JSONRPCException:
        # If the transaction is not found.
        assert False

    # Now let's mine some blocks so the appointment reaches its end. We need 100 + EXPIRY_DELTA -1
    generate_blocks(100 + config.get("EXPIRY_DELTA") - 1)
    appointments_in_responder -= 1

    # The appointment is no longer in the tower
    with pytest.raises(TowerResponseError):
        get_appointment_info(teos_id, locator)

    assert get_subscription_info(teos_id).get("available_slots") == available_slots