Exemple #1
0
def test_mediation(raiden_network, token_addresses, settle_timeout):
    # The network has the following topology:
    #
    # App1 <--> App0 <--> App2

    token_address = token_addresses[0]
    app0, app1, app2 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    identifier = 1
    amount = 1
    async_result = app1.raiden.mediated_transfer_async(
        token_address,
        amount,
        app2.raiden.address,
        identifier,
    )
    assert async_result.wait()

    mediator_chain = app0.raiden.chain
    settle_expiration = mediator_chain.block_number() + settle_timeout + 1
    wait_until_block(mediator_chain, settle_expiration)

    # context switch needed for tester to process the EventWithdrawSuccess
    gevent.sleep(1)

    app0_events = [
        event.event_object
        for event in get_all_state_events(app0.raiden.transaction_log)
    ]
    assert must_contain_entry(app0_events, EventWithdrawSuccess, {})
Exemple #2
0
def test_channel_with_self(raiden_network, settle_timeout, token_addresses):
    app0, = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]

    current_chanels = views.list_channelstate_for_tokennetwork(
        views.state_from_app(app0),
        registry_address,
        token_address,
    )
    assert not current_chanels

    graph0 = app0.raiden.default_registry.manager_by_token(token_address)

    with pytest.raises(SamePeerAddress) as excinfo:
        graph0.new_netting_channel(
            app0.raiden.address,
            settle_timeout,
        )

    assert 'The other peer must not have the same address as the client.' in str(excinfo.value)

    transaction_hash = graph0.proxy.transact('newChannel', app0.raiden.address, settle_timeout)

    # wait to make sure we get the receipt
    wait_until_block(app0.raiden.chain, app0.raiden.chain.block_number() + 5)
    assert check_transaction_threw(app0.raiden.chain.client, transaction_hash)
def test_channel_with_self(raiden_network, settle_timeout):
    app0, = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    token_address = app0.raiden.default_registry.token_addresses()[0]

    assert not app0.raiden.token_to_channelgraph[token_address].address_to_channel

    graph0 = app0.raiden.default_registry.manager_by_token(token_address)

    with pytest.raises(SamePeerAddress) as excinfo:
        graph0.new_netting_channel(
            app0.raiden.address,
            settle_timeout,
        )

    assert 'The other peer must not have the same address as the client.' in str(excinfo.value)

    transaction_hash = graph0.proxy.transact(
        'newChannel',
        app0.raiden.address,
        settle_timeout,
    )

    # wait to make sure we get the receipt
    wait_until_block(app0.raiden.chain, app0.raiden.chain.block_number() + 5)
    assert check_transaction_threw(app0.raiden.chain.client, transaction_hash)
def test_channel_with_self(raiden_network, settle_timeout, blockchain_type):
    app0, = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    token_address = app0.raiden.chain.default_registry.token_addresses()[0]

    assert len(app0.raiden.token_to_channelgraph[token_address].address_to_channel) == 0

    graph0 = app0.raiden.chain.manager_by_token(token_address)

    with pytest.raises(SamePeerAddress) as excinfo:
        graph0.new_netting_channel(
            app0.raiden.address,
            app0.raiden.address,
            settle_timeout,
        )
        assert 'Peer1 and peer2 must not be equal' in str(excinfo.value)

    if blockchain_type == 'tester':
        with pytest.raises(TransactionFailed):
            graph0.proxy.newChannel(app0.raiden.address, settle_timeout)
    else:
        tx = graph0.proxy.newChannel(app0.raiden.address, settle_timeout)
        # wait to make sure we get the receipt
        wait_until_block(app0.raiden.chain, app0.raiden.chain.block_number() + 5)
        assert check_transaction_threw(app0.raiden.chain.client, tx) is True
def test_mediation(raiden_network, token_addresses, settle_timeout):
    # The network has the following topology:
    #
    # App1 <--> App0 <--> App2

    token_address = token_addresses[0]
    app0, app1, app2 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    identifier = 1
    amount = 1
    async_result = app1.raiden.mediated_transfer_async(
        token_address,
        amount,
        app2.raiden.address,
        identifier,
    )
    assert async_result.wait()

    mediator_chain = app0.raiden.chain
    settle_expiration = mediator_chain.block_number() + settle_timeout + 1
    wait_until_block(mediator_chain, settle_expiration)

    # context switch needed for tester to process the EventWithdrawSuccess
    gevent.sleep(1)

    app0_events = [
        event.event_object
        for event in get_all_state_events(app0.raiden.transaction_log)
    ]
    assert must_contain_entry(app0_events, EventWithdrawSuccess, {})
Exemple #6
0
def test_transfer_from_outdated(raiden_network, settle_timeout):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    graph0 = app0.raiden.token_to_channelgraph.values()[0]
    graph1 = app1.raiden.token_to_channelgraph.values()[0]

    channel0 = graph0.partneraddress_to_channel[app1.raiden.address]
    channel1 = graph1.partneraddress_to_channel[app0.raiden.address]

    balance0 = channel0.balance
    balance1 = channel1.balance

    assert graph0.token_address == graph1.token_address
    assert app1.raiden.address in graph0.partneraddress_to_channel

    amount = 10
    result = app0.raiden.transfer_async(
        graph0.token_address,
        amount,
        target=app1.raiden.address,
    )

    assert result.wait(timeout=10)

    assert_synched_channels(channel0, balance0 - amount, [], channel1,
                            balance1 + amount, [])

    channel1.external_state.close(channel1.received_transfers[-1], )

    wait_until_block(app1.raiden.chain, app1.raiden.chain.block_number() + 1)

    assert channel0.external_state.close_event.wait(timeout=25)
    assert channel1.external_state.close_event.wait(timeout=25)

    assert channel0.external_state.closed_block != 0
    assert channel1.external_state.closed_block != 0

    wait_until_block(
        app0.raiden.chain,
        app0.raiden.chain.block_number() + settle_timeout,
    )

    assert channel0.external_state.settle_event.wait(timeout=25)
    assert channel1.external_state.settle_event.wait(timeout=25)

    assert channel0.external_state.settled_block != 0
    assert channel1.external_state.settled_block != 0

    # and now receive one more transfer from the closed channel
    direct_transfer_message = DirectTransfer(
        identifier=1,
        nonce=1,
        token=graph0.token_address,
        channel=channel0.channel_address,
        transferred_amount=10,
        recipient=app0.raiden.address,
        locksroot=UNIT_HASHLOCK,
    )
    sign_and_send(direct_transfer_message, app1.raiden.private_key,
                  app1.raiden.address, app1)
Exemple #7
0
def test_leaving(raiden_network, token_addresses, blockchain_type):
    token_address = token_addresses[0]
    connection_managers = [
        app.raiden.connection_manager_for_token(token_address)
        for app in raiden_network
    ]

    all_channels = list(
        itertools.chain.from_iterable(
            connection_manager.receiving_channels
            for connection_manager in connection_managers))

    leaving_async = [
        app.raiden.leave_all_token_networks_async()
        for app in raiden_network[1:]
    ]

    with gevent.timeout.Timeout(30):
        # tester needs manual block progress
        if blockchain_type == 'tester':
            for app in raiden_network:
                connection_manager = app.raiden.connection_manager_for_token(
                    token_address)
                wait_blocks = connection_manager.min_settle_blocks
                if wait_blocks > 0:
                    wait_until_block(
                        app.raiden.chain,
                        app.raiden.chain.block_number() + wait_blocks)
                    gevent.sleep(app.raiden.alarm.wait_time)

    gevent.wait(leaving_async, timeout=50)

    assert not connection_managers[0].receiving_channels
    assert all(channel.state == CHANNEL_STATE_SETTLED
               for channel in all_channels)
Exemple #8
0
def test_secret_revealed(raiden_chain, deposit, settle_timeout,
                         events_poll_timeout):
    app0, app1, app2 = raiden_chain

    asset_address = app0.raiden.chain.default_registry.asset_addresses()[0]
    amount = 10

    channel21 = channel(app2, app1, asset_address)
    netting_channel = channel21.external_state.netting_channel

    secret = pending_mediated_transfer(
        raiden_chain,
        asset_address,
        amount,
        1  # TODO: fill in identifier
    )
    hashlock = sha3(secret)

    gevent.sleep(.1)  # wait for the messages

    balance_proof = channel21.our_state.balance_proof
    lock = balance_proof.get_lock_by_hashlock(hashlock)
    proof = balance_proof.compute_proof_for_lock(secret, lock)

    # the secret hasn't been revealed yet (through messages)
    assert len(balance_proof.hashlock_pendinglocks) == 1
    proofs = list(balance_proof.get_known_unlocks())
    assert len(proofs) == 0

    netting_channel.close(app2.raiden.address, balance_proof.transfer, None)

    # reveal it through the blockchain (this needs to emit the SecretRevealed event)
    netting_channel.unlock(
        app2.raiden.address,
        [proof],
    )

    settle_expiration = app0.raiden.chain.block_number() + settle_timeout
    wait_until_block(app0.raiden.chain, settle_expiration)

    channel21.settle_event.wait(timeout=10)

    assert_synched_channels(
        channel(app1, app2, asset_address),
        deposit - amount,
        [],
        channel(app2, app1, asset_address),
        deposit + amount,
        [],
    )

    assert_synched_channels(
        channel(app0, app1, asset_address),
        deposit - amount,
        [],
        channel(app1, app2, asset_address),
        deposit + amount,
        [],
    )
def test_settled_lock(token_addresses, raiden_network, settle_timeout, reveal_timeout):
    """ Any transfer following a secret revealed must update the locksroot, so
    that an attacker cannot reuse a secret to double claim a lock.
    """
    token = token_addresses[0]
    amount = 30

    app0, app1, app2, _ = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    address0 = app0.raiden.address
    address1 = app1.raiden.address

    forward_channel = channel(app0, app1, token)
    back_channel = channel(app1, app0, token)

    deposit0 = forward_channel.contract_balance
    deposit1 = back_channel.contract_balance

    token_contract = app0.raiden.chain.token(token)
    balance0 = token_contract.balance_of(address0)
    balance1 = token_contract.balance_of(address1)

    # A pending mediated transfer
    identifier = 1
    expiration = app0.raiden.chain.block_number() + settle_timeout - reveal_timeout
    secret = pending_mediated_transfer(
        raiden_network,
        token,
        amount,
        identifier,
        expiration,
    )
    hashlock = sha3(secret)

    # Get the proof to unlock the pending lock
    secret_transfer = get_received_transfer(back_channel, 0)
    lock = back_channel.partner_state.get_lock_by_hashlock(hashlock)
    unlock_proof = back_channel.partner_state.compute_proof_for_lock(secret, lock)

    # Update the hashlock
    claim_lock(raiden_network, identifier, token, secret)
    direct_transfer(app0, app1, token, amount, identifier=1)

    # The direct transfer locksroot must remove the unlocked lock and update
    # the transferred amount, the withdraw must fail.
    balance_proof = back_channel.partner_state.balance_proof
    back_channel.external_state.close(balance_proof)
    with pytest.raises(Exception):
        back_channel.external_state.netting_channel.withdraw(
            [(unlock_proof, secret_transfer.lock.as_bytes, secret)],
        )

    settle_expiration = app2.raiden.chain.block_number() + settle_timeout
    wait_until_block(app2.raiden.chain, settle_expiration)
    back_channel.external_state.netting_channel.settle()

    assert token_contract.balance_of(address0) == balance0 + deposit0 - amount * 2
    assert token_contract.balance_of(address1) == balance1 + deposit1 + amount * 2
Exemple #10
0
def test_secret_revealed(raiden_chain, deposit, settle_timeout, token_addresses):
    app0, app1, app2 = raiden_chain
    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_registry.address,
        token_address,
    )

    amount = 10
    identifier = 1
    secret = pending_mediated_transfer(
        raiden_chain,
        token_network_identifier,
        amount,
        identifier,
    )
    secrethash = sha3(secret)

    gevent.sleep(.1)  # wait for the messages

    channel_state2_1 = get_channelstate(app2, app1, token_network_identifier)

    # the secret hasn't been revealed yet (through messages)

    assert len(channel_state2_1.our_state.secrethashes_to_lockedlocks) == 1
    proofs = list(channel.get_known_unlocks(channel_state2_1.our_state))
    assert not proofs

    channel.register_secret(channel_state2_1, secret, secrethash)

    # Close the channel
    netting_channel_proxy = app2.raiden.chain.netting_channel(channel_state2_1.identifier)
    netting_channel_proxy.channel_close(
        registry_address,
        channel_state2_1.partner_state.balance_proof,
    )

    # Reveal the secret through the blockchain (this needs to emit the
    # SecretRevealed event)
    for unlock_proof in channel.get_known_unlocks(channel_state2_1.partner_state):
        netting_channel_proxy.unlock(unlock_proof)

    settle_expiration = app0.raiden.chain.block_number() + settle_timeout
    wait_until_block(app0.raiden.chain, settle_expiration)

    assert_synched_channel_state(
        token_address,
        app1, deposit - amount, [],
        app2, deposit + amount, [],
    )

    assert_synched_channel_state(
        token_address,
        app0, deposit - amount, [],
        app1, deposit + amount, [],
    )
Exemple #11
0
def test_received_lockedtransfer_closedchannel(raiden_network, reveal_timeout,
                                               token_addresses, deposit):

    app0, app1 = raiden_network
    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]
    channel0 = get_channelstate(app0, app1, token_address)

    RaidenAPI(app1.raiden).channel_close(
        registry_address,
        token_address,
        app0.raiden.address,
    )

    wait_until_block(
        app0.raiden.chain,
        app0.raiden.chain.block_number() + 1,
    )

    # Now receive one mediated transfer for the closed channel
    lock_amount = 10
    payment_identifier = 1
    expiration = reveal_timeout * 2
    mediated_transfer_message = LockedTransfer(
        message_identifier=random.randint(0, UINT64_MAX),
        payment_identifier=payment_identifier,
        nonce=1,
        registry_address=app0.raiden.default_registry.address,
        token=token_address,
        channel=channel0.identifier,
        transferred_amount=0,
        locked_amount=lock_amount,
        recipient=app1.raiden.address,
        locksroot=UNIT_SECRETHASH,
        lock=Lock(lock_amount, expiration, UNIT_SECRETHASH),
        target=app1.raiden.address,
        initiator=app0.raiden.address,
        fee=0)

    sign_and_inject(
        mediated_transfer_message,
        app0.raiden.private_key,
        app0.raiden.address,
        app1,
    )

    # The local state must not change since the channel is already closed
    assert_synched_channel_state(
        token_address,
        app0,
        deposit,
        [],
        app1,
        deposit,
        [],
    )
Exemple #12
0
def test_received_directtransfer_closedchannel(raiden_network, token_addresses,
                                               deposit):
    app0, app1 = raiden_network
    token_address = token_addresses[0]
    registry_address = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        registry_address,
        token_address,
    )
    channel0 = get_channelstate(app0, app1, token_network_identifier)

    RaidenAPI(app1.raiden).channel_close(
        registry_address,
        token_address,
        app0.raiden.address,
    )

    wait_until_block(
        app0.raiden.chain,
        app0.raiden.chain.block_number() + 1,
    )

    # Now receive one direct transfer for the closed channel
    message_identifier = random.randint(0, UINT64_MAX)
    direct_transfer_message = DirectTransfer(
        message_identifier=message_identifier,
        payment_identifier=1,
        nonce=1,
        token_network_address=token_network_identifier,
        token=token_address,
        channel=channel0.identifier,
        transferred_amount=10,
        locked_amount=0,
        recipient=app0.raiden.address,
        locksroot=EMPTY_MERKLE_ROOT,
    )

    sign_and_inject(
        direct_transfer_message,
        app0.raiden.private_key,
        app0.raiden.address,
        app1,
    )

    # The local state must not change since the channel is already closed
    assert_synched_channel_state(
        token_network_identifier,
        app0,
        deposit,
        [],
        app1,
        deposit,
        [],
    )
Exemple #13
0
def test_transfer_from_outdated(raiden_network, settle_timeout):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    token_manager0 = app0.raiden.managers_by_token_address.values()[0]
    token_manager1 = app1.raiden.managers_by_token_address.values()[0]

    channel0 = token_manager0.partneraddress_channel[app1.raiden.address]
    channel1 = token_manager1.partneraddress_channel[app0.raiden.address]

    balance0 = channel0.balance
    balance1 = channel1.balance

    assert token_manager0.token_address == token_manager1.token_address
    assert app1.raiden.address in token_manager0.partneraddress_channel

    amount = 10
    app0.raiden.api.transfer(
        token_manager0.token_address,
        amount,
        target=app1.raiden.address,
    )

    assert_synched_channels(channel0, balance0 - amount, [], channel1,
                            balance1 + amount, [])

    app1.raiden.api.close(token_manager0.token_address, app0.raiden.address)

    wait_until_block(app1.raiden.chain, app1.raiden.chain.block_number() + 1)

    assert channel0.close_event.wait(timeout=25)
    assert channel1.close_event.wait(timeout=25)

    assert channel0.external_state.closed_block != 0
    assert channel1.external_state.closed_block != 0

    wait_until_block(
        app0.raiden.chain,
        app0.raiden.chain.block_number() + settle_timeout,
    )

    assert channel0.settle_event.wait(timeout=25)
    assert channel1.settle_event.wait(timeout=25)

    assert channel0.external_state.settled_block != 0
    assert channel1.external_state.settled_block != 0

    # and now receive one more transfer from the closed channel
    direct_transfer = DirectTransfer(identifier=1,
                                     nonce=1,
                                     token=token_manager0.token_address,
                                     transferred_amount=10,
                                     recipient=app0.raiden.address,
                                     locksroot=HASH)
    sign_and_send(direct_transfer, app1.raiden.private_key,
                  app1.raiden.address, app1)
Exemple #14
0
def test_settled_lock(assets_addresses, raiden_network, settle_timeout):
    """ Any transfer following a secret revealed must update the locksroot, so
    that an attacker cannot reuse a secret to double claim a lock.
    """
    asset = assets_addresses[0]
    amount = 30

    app0, app1, app2, app3 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    # mediated transfer
    secret = pending_mediated_transfer(raiden_network, asset, amount)
    hashlock = sha3(secret)

    # get a proof for the pending transfer
    back_channel = channel(app1, app0, asset)
    secret_transfer = get_received_transfer(back_channel, 0)
    lock = back_channel.our_state.balance_proof.get_lock_by_hashlock(hashlock)
    unlock_proof = back_channel.our_state.balance_proof.compute_proof_for_lock(
        secret, lock)

    # reveal the secret
    claim_lock(raiden_network, asset, secret)

    # a new transfer to update the hashlock
    direct_transfer(app0, app1, asset, amount)

    forward_channel = channel(app0, app1, asset)
    last_transfer = get_sent_transfer(forward_channel, 1)

    # call close giving the secret for a transfer that has being revealed
    back_channel.external_state.netting_channel.close(app1.raiden.address,
                                                      last_transfer, None)

    # check that the double unlock will failed
    with pytest.raises(Exception):
        back_channel.external_state.netting_channel.unlock(
            app1.raiden.address,
            [(unlock_proof, secret_transfer.lock.as_bytes, secret)],
        )

    # forward the block number to allow settle
    settle_expiration = app2.raiden.chain.block_number() + settle_timeout
    wait_until_block(app2.raiden.chain, settle_expiration)

    back_channel.external_state.netting_channel.settle()

    participant0 = back_channel.external_state.netting_channel.contract.participants[
        app0.raiden.address]
    participant1 = back_channel.external_state.netting_channel.contract.participants[
        app1.raiden.address]

    assert participant0.netted == participant0.deposit - amount * 2
    assert participant1.netted == participant1.deposit + amount * 2
def test_secret_revealed(raiden_chain, deposit, settle_timeout, events_poll_timeout):
    app0, app1, app2 = raiden_chain

    token_address = app0.raiden.default_registry.token_addresses()[0]
    amount = 10

    channel21 = channel(app2, app1, token_address)
    netting_channel = channel21.external_state.netting_channel

    identifier = 1
    expiration = app2.raiden.get_block_number() + settle_timeout - 3

    secret = pending_mediated_transfer(
        raiden_chain,
        token_address,
        amount,
        identifier,
        expiration,
    )
    hashlock = sha3(secret)

    gevent.sleep(.1)  # wait for the messages

    lock = channel21.our_state.get_lock_by_hashlock(hashlock)
    proof = channel21.our_state.compute_proof_for_lock(secret, lock)

    # the secret hasn't been revealed yet (through messages)
    assert len(channel21.our_state.hashlocks_to_pendinglocks) == 1
    proofs = list(channel21.our_state.get_known_unlocks())
    assert len(proofs) == 0

    netting_channel.close(channel21.our_state.balance_proof)

    # reveal it through the blockchain (this needs to emit the SecretRevealed event)
    netting_channel.withdraw(
        app2.raiden.address,
        [proof],
    )

    settle_expiration = app0.raiden.chain.block_number() + settle_timeout
    wait_until_block(app0.raiden.chain, settle_expiration)

    channel21.settle_event.wait(timeout=10)

    assert_synched_channels(
        channel(app1, app2, token_address), deposit - amount, [],
        channel(app2, app1, token_address), deposit + amount, [],
    )

    assert_synched_channels(
        channel(app0, app1, token_address), deposit - amount, [],
        channel(app1, app2, token_address), deposit + amount, [],
    )
def test_close_regression(blockchain_type, raiden_network, token_addresses):
    """ The python api was using the wrong balance proof to close the channel,
    thus the close was failling if a transfer was made.
    """
    if blockchain_type == 'tester':
        pytest.skip('event polling is not reliable')

    node1, node2 = raiden_network
    token_address = token_addresses[0]

    api1 = RaidenAPI(node1.raiden)
    api2 = RaidenAPI(node2.raiden)

    channel_list = api1.get_channel_list(token_address, node2.raiden.address)
    channel12 = channel_list[0]

    token_proxy = node1.raiden.chain.token(token_address)
    node1_balance_before = token_proxy.balance_of(api1.address)
    node2_balance_before = token_proxy.balance_of(api2.address)
    channel_balance = token_proxy.balance_of(channel12.channel_address)

    amount = 10
    assert api1.transfer(token_address, amount, api2.address)

    api1.close(token_address, api2.address)

    node1.raiden.poll_blockchain_events()
    assert channel12.state == CHANNEL_STATE_CLOSED

    settlement_block = (
        channel12.external_state.closed_block + channel12.settle_timeout +
        5  # arbitrary number of additional blocks, used to wait for the settle() call
    )
    wait_until_block(node1.raiden.chain, settlement_block)

    node1.raiden.poll_blockchain_events()
    assert channel12.state == CHANNEL_STATE_SETTLED

    node1_withdraw_amount = channel12.balance
    node2_withdraw_amount = channel_balance - node1_withdraw_amount

    assert token_proxy.balance_of(
        api1.address) == node1_balance_before + node1_withdraw_amount
    assert token_proxy.balance_of(
        api2.address) == node2_balance_before + node2_withdraw_amount
Exemple #17
0
def test_received_directtransfer_closedchannel(raiden_network, token_addresses,
                                               deposit):
    app0, app1 = raiden_network
    token_address = token_addresses[0]
    channel0 = get_channelstate(app0, app1, token_address)

    RaidenAPI(app1.raiden).channel_close(
        token_address,
        app0.raiden.address,
    )

    wait_until_block(
        app0.raiden.chain,
        app0.raiden.chain.block_number() + 1,
    )

    # Now receive one direct transfer for the closed channel
    direct_transfer_message = DirectTransfer(
        identifier=1,
        nonce=1,
        token=token_address,
        channel=channel0.identifier,
        transferred_amount=10,
        recipient=app0.raiden.address,
        locksroot=EMPTY_MERKLE_ROOT,
    )

    sign_and_inject(
        direct_transfer_message,
        app0.raiden.private_key,
        app0.raiden.address,
        app1,
    )

    # The local state must not change since the channel is already closed
    assert_synched_channel_state(
        token_address,
        app0,
        deposit,
        [],
        app1,
        deposit,
        [],
    )
def test_close_channel_lack_of_balance_proof(
        raiden_chain,
        reveal_timeout,
        settle_timeout,
        token_addresses):

    app0, app1 = raiden_chain
    token_address = token_addresses[0]

    channel01 = channel(app0, app1, token_address)

    secret = sha3(b'test_close_channel_lack_of_balance_proof')
    hashlock = sha3(secret)

    fee = 0
    amount = 100
    identifier = 1
    expiration = app0.raiden.get_block_number() + reveal_timeout * 2
    transfer = channel01.create_mediatedtransfer(
        app0.raiden.address,
        app1.raiden.address,
        fee,
        amount,
        identifier,
        expiration,
        hashlock,
    )
    app0.raiden.sign(transfer)
    async_result = app0.raiden.send_async(app1.raiden.address, transfer)
    assert async_result.wait()

    reveal_secret = RevealSecret(secret)
    app0.raiden.sign(reveal_secret)
    async_result = app0.raiden.send_async(app1.raiden.address, reveal_secret)
    assert async_result.wait()

    wait_until = app0.raiden.get_block_number() + settle_timeout + 2
    wait_until_block(app0.raiden.chain, wait_until)

    # required for tester blockchain: let the alarm task run
    gevent.sleep(1)

    assert channel01.state != CHANNEL_STATE_OPENED
Exemple #19
0
def test_close_channel_lack_of_balance_proof(
        raiden_chain,
        reveal_timeout,
        settle_timeout,
        token_addresses):

    app0, app1 = raiden_chain
    token_address = token_addresses[0]

    channel01 = channel(app0, app1, token_address)

    secret = sha3('test_close_channel_lack_of_balance_proof')
    hashlock = sha3(secret)

    fee = 0
    amount = 100
    identifier = 1
    expiration = app0.raiden.get_block_number() + reveal_timeout * 2
    transfer = channel01.create_mediatedtransfer(
        app0.raiden.address,
        app1.raiden.address,
        fee,
        amount,
        identifier,
        expiration,
        hashlock,
    )
    app0.raiden.sign(transfer)
    async_result = app0.raiden.send_async(app1.raiden.address, transfer)
    assert async_result.wait()

    reveal_secret = RevealSecret(secret)
    app0.raiden.sign(reveal_secret)
    async_result = app0.raiden.send_async(app1.raiden.address, reveal_secret)
    assert async_result.wait()

    wait_until = app0.raiden.get_block_number() + settle_timeout + 2
    wait_until_block(app0.raiden.chain, wait_until)

    # required for tester blockchain: let the alarm task run
    gevent.sleep(1)

    assert channel01.state != CHANNEL_STATE_OPENED
Exemple #20
0
def test_channel_lifecycle(raiden_network, token_addresses, deposit,
                           transport_config):
    node1, node2 = raiden_network
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(node1),
        node1.raiden.default_registry.address,
        token_address,
    )

    api1 = RaidenAPI(node1.raiden)
    api2 = RaidenAPI(node2.raiden)

    registry_address = node1.raiden.default_registry.address

    if transport_config.protocol == TransportProtocol.UDP:
        # nodes don't have a channel, so they are not healthchecking
        assert api1.get_node_network_state(
            api2.address) == NODE_NETWORK_UNKNOWN
        assert api2.get_node_network_state(
            api1.address) == NODE_NETWORK_UNKNOWN
    elif transport_config.protocol == TransportProtocol.MATRIX:
        # with Matrix nodes do not need a health check to know each others reachability
        assert api1.get_node_network_state(
            api2.address) == NODE_NETWORK_UNREACHABLE
        assert api2.get_node_network_state(
            api1.address) == NODE_NETWORK_UNREACHABLE
    assert not api1.get_channel_list(registry_address, token_address,
                                     api2.address)

    # open is a synchronous api
    api1.channel_open(node1.raiden.default_registry.address, token_address,
                      api2.address)
    channels = api1.get_channel_list(registry_address, token_address,
                                     api2.address)
    assert len(channels) == 1

    channel12 = get_channelstate(node1, node2, token_network_identifier)
    assert channel.get_status(channel12) == CHANNEL_STATE_OPENED

    event_list1 = api1.get_channel_events(
        channel12.identifier,
        channel12.open_transaction.finished_block_number,
    )
    assert event_list1 == []

    token_events = api1.get_token_network_events(
        token_address,
        channel12.open_transaction.finished_block_number,
    )
    assert token_events[0]['event'] == EVENT_CHANNEL_NEW

    registry_address = api1.raiden.default_registry.address
    # Load the new state with the deposit
    api1.channel_deposit(
        registry_address,
        token_address,
        api2.address,
        deposit,
    )

    channel12 = get_channelstate(node1, node2, token_network_identifier)

    assert channel.get_status(channel12) == CHANNEL_STATE_OPENED
    assert channel.get_balance(channel12.our_state,
                               channel12.partner_state) == deposit
    assert channel12.our_state.contract_balance == deposit
    assert api1.get_channel_list(registry_address, token_address,
                                 api2.address) == [channel12]

    # there is a channel open, they must be healthchecking each other
    assert api1.get_node_network_state(api2.address) == NODE_NETWORK_REACHABLE
    assert api2.get_node_network_state(api1.address) == NODE_NETWORK_REACHABLE

    event_list2 = api1.get_channel_events(
        channel12.identifier,
        channel12.open_transaction.finished_block_number,
    )
    assert any(
        (event['event'] == EVENT_CHANNEL_NEW_BALANCE and is_same_address(
            event['args']['registry_address'],
            to_normalized_address(registry_address),
        ) and is_same_address(
            event['args']['participant'],
            to_normalized_address(api1.address),
        )) for event in event_list2)

    api1.channel_close(registry_address, token_address, api2.address)

    # Load the new state with the channel closed
    channel12 = get_channelstate(node1, node2, token_network_identifier)

    event_list3 = api1.get_channel_events(
        channel12.identifier,
        channel12.open_transaction.finished_block_number,
    )
    assert len(event_list3) > len(event_list2)
    assert any((event['event'] == EVENT_CHANNEL_CLOSED and is_same_address(
        event['args']['registry_address'],
        to_normalized_address(registry_address),
    ) and is_same_address(
        event['args']['closing_address'],
        to_normalized_address(api1.address),
    )) for event in event_list3)
    assert channel.get_status(channel12) == CHANNEL_STATE_CLOSED

    settlement_block = (
        channel12.close_transaction.finished_block_number +
        channel12.settle_timeout +
        10  # arbitrary number of additional blocks, used to wait for the settle() call
    )
    wait_until_block(node1.raiden.chain, settlement_block)

    # Load the new state with the channel settled
    channel12 = get_channelstate(node1, node2, token_network_identifier)

    assert channel.get_status(channel12) == CHANNEL_STATE_SETTLED
Exemple #21
0
def test_query_events(raiden_chain, deposit, settle_timeout,
                      events_poll_timeout):
    app0, app1 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking

    token_address = app0.raiden.default_registry.token_addresses()[0]

    assert len(app0.raiden.token_to_channelgraph[token_address].
               address_to_channel) == 0
    assert len(app1.raiden.token_to_channelgraph[token_address].
               address_to_channel) == 0

    token0 = app0.raiden.chain.token(token_address)
    manager0 = app0.raiden.default_registry.manager_by_token(token_address)

    events = get_all_registry_events(
        app0.raiden.chain,
        app0.raiden.default_registry.address,
        events=ALL_EVENTS,
        from_block=0,
        to_block='latest',
    )

    assert len(events) == 1
    assert event_dicts_are_equal(
        events[0], {
            '_event_type': 'TokenAdded',
            'channel_manager_address': address_encoder(manager0.address),
            'token_address': address_encoder(token_address),
            'block_number': 'ignore',
        })

    events = get_all_registry_events(
        app0.raiden.chain,
        app0.raiden.default_registry.address,
        events=ALL_EVENTS,
        from_block=999999998,
        to_block=999999999,
    )
    assert not events

    netcontract_address = manager0.new_netting_channel(
        app0.raiden.address,
        app1.raiden.address,
        settle_timeout,
    )

    events = get_all_channel_manager_events(
        app0.raiden.chain,
        manager0.address,
        events=ALL_EVENTS,
        from_block=0,
        to_block='latest',
    )

    assert len(events) == 1
    assert event_dicts_are_equal(
        events[0], {
            '_event_type': 'ChannelNew',
            'settle_timeout': settle_timeout,
            'netting_channel': address_encoder(netcontract_address),
            'participant1': address_encoder(app0.raiden.address),
            'participant2': address_encoder(app1.raiden.address),
            'block_number': 'ignore',
        })

    events = get_all_channel_manager_events(
        app0.raiden.chain,
        manager0.address,
        events=ALL_EVENTS,
        from_block=999999998,
        to_block=999999999,
    )
    assert not events

    netting_channel0 = app0.raiden.chain.netting_channel(netcontract_address)

    gevent.sleep(events_poll_timeout * 2)

    # channel is created but not opened and without funds
    assert len(app0.raiden.token_to_channelgraph[token_address].
               address_to_channel) == 1
    assert len(app1.raiden.token_to_channelgraph[token_address].
               address_to_channel) == 1

    channel0 = app0.raiden.token_to_channelgraph[
        token_address].address_to_channel.values()[0]
    channel1 = app1.raiden.token_to_channelgraph[
        token_address].address_to_channel.values()[0]

    assert_synched_channels(
        channel0,
        0,
        [],
        channel1,
        0,
        [],
    )

    token0.approve(netcontract_address, deposit)
    netting_channel0.deposit(deposit)

    all_netting_channel_events = get_all_netting_channel_events(
        app0.raiden.chain,
        netting_channel_address=netcontract_address,
        from_block=0,
        to_block='latest',
    )

    events = get_all_netting_channel_events(
        app0.raiden.chain,
        netcontract_address,
        events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_NEW_BALANCE)],
    )

    assert len(all_netting_channel_events) == 1
    assert len(events) == 1

    new_balance_event = {
        '_event_type': 'ChannelNewBalance',
        'token_address': address_encoder(token_address),
        'participant': address_encoder(app0.raiden.address),
        'balance': deposit,
        'block_number': 'ignore',
    }

    assert event_dicts_are_equal(all_netting_channel_events[-1],
                                 new_balance_event)
    assert event_dicts_are_equal(events[0], new_balance_event)

    channel0.external_state.close(None)

    all_netting_channel_events = get_all_netting_channel_events(
        app0.raiden.chain,
        netting_channel_address=netcontract_address,
        from_block=0,
        to_block='latest',
    )

    events = get_all_netting_channel_events(
        app0.raiden.chain,
        netcontract_address,
        events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_CLOSED)],
    )

    assert len(all_netting_channel_events) == 2
    assert len(events) == 1

    closed_event = {
        '_event_type': 'ChannelClosed',
        'closing_address': address_encoder(app0.raiden.address),
        'block_number': 'ignore',
    }

    assert event_dicts_are_equal(all_netting_channel_events[-1], closed_event)
    assert event_dicts_are_equal(events[0], closed_event)

    settle_expiration = app0.raiden.chain.block_number() + settle_timeout + 1
    wait_until_block(app0.raiden.chain, settle_expiration)

    channel1.external_state.settle()

    all_netting_channel_events = get_all_netting_channel_events(
        app0.raiden.chain,
        netting_channel_address=netcontract_address,
        from_block=0,
        to_block='latest',
    )

    events = get_all_netting_channel_events(
        app0.raiden.chain,
        netcontract_address,
        events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_SETTLED)],
    )

    assert len(all_netting_channel_events) == 3
    assert len(events) == 1

    settled_event = {
        '_event_type': 'ChannelSettled',
        'block_number': 'ignore',
    }

    assert event_dicts_are_equal(all_netting_channel_events[-1], settled_event)
    assert event_dicts_are_equal(events[0], settled_event)
def test_participant_selection(raiden_network, token_addresses):
    # pylint: disable=too-many-locals
    token_address = token_addresses[0]

    # connect the first node (will register the token if necessary)
    RaidenAPI(raiden_network[0].raiden).connect_token_network(token_address, 100)

    # connect the other nodes
    connect_greenlets = [
        gevent.spawn(RaidenAPI(app.raiden).connect_token_network, token_address, 100)
        for app in raiden_network[1:]
    ]
    gevent.wait(connect_greenlets)

    # wait some blocks to let the network connect
    wait_blocks = 15
    for _ in range(wait_blocks):
        for app in raiden_network:
            wait_until_block(
                app.raiden.chain,
                app.raiden.chain.block_number() + 1
            )

    connection_managers = [
        app.raiden.connection_manager_for_token(token_address) for app in raiden_network
    ]

    def open_channels_count(connection_managers_):
        return [
            connection_manager.open_channels for connection_manager in connection_managers_
        ]

    assert all(open_channels_count(connection_managers))

    def not_saturated(connection_managers_):
        return [
            1 for connection_manager_ in connection_managers_
            if len(connection_manager_.open_channels) < connection_manager_.initial_channel_target
        ]

    chain = raiden_network[-1].raiden.chain
    max_wait = 12

    while not_saturated(connection_managers) and max_wait > 0:
        wait_until_block(chain, chain.block_number() + 1)
        max_wait -= 1

    assert not not_saturated(connection_managers)

    # Ensure unpartitioned network
    addresses = [app.raiden.address for app in raiden_network]
    for connection_manager in connection_managers:
        assert all(
            connection_manager.channelgraph.has_path(
                connection_manager.raiden.address,
                address
            )
            for address in addresses
        )

    # average channel count
    acc = (
        sum(len(connection_manager.open_channels) for connection_manager in connection_managers) /
        len(connection_managers)
    )

    try:
        # FIXME: depending on the number of channels, this will fail, due to weak
        # selection algorithm
        # https://github.com/raiden-network/raiden/issues/576
        assert not any(
            len(connection_manager.open_channels) > 2 * acc
            for connection_manager in connection_managers
        )
    except AssertionError:
        pass

    # create a transfer to the leaving node, so we have a channel to settle
    sender = raiden_network[-1].raiden
    receiver = raiden_network[0].raiden

    # assert there is a direct channel receiver -> sender (vv)
    receiver_channel = RaidenAPI(receiver).get_channel_list(
        token_address=token_address,
        partner_address=sender.address
    )
    assert len(receiver_channel) == 1
    receiver_channel = receiver_channel[0]
    assert receiver_channel.external_state.opened_block != 0
    assert not receiver_channel.received_transfers

    # assert there is a direct channel sender -> receiver
    sender_channel = RaidenAPI(sender).get_channel_list(
        token_address=token_address,
        partner_address=receiver.address
    )
    assert len(sender_channel) == 1
    sender_channel = sender_channel[0]
    assert sender_channel.can_transfer
    assert sender_channel.external_state.opened_block != 0

    RaidenAPI(sender).transfer_and_wait(
        token_address,
        1,
        receiver.address
    )

    # now receiver has a transfer
    assert len(receiver_channel.received_transfers)

    # test `leave()` method
    connection_manager = connection_managers[0]
    before = len(connection_manager.receiving_channels)

    timeout = (
        connection_manager.min_settle_blocks *
        connection_manager.raiden.chain.estimate_blocktime() *
        5
    )

    assert timeout > 0
    with gevent.timeout.Timeout(timeout):
        try:
            RaidenAPI(raiden_network[0].raiden).leave_token_network(token_address)
        except gevent.timeout.Timeout:
            log.error('timeout while waiting for leave')

    before_block = connection_manager.raiden.chain.block_number()
    wait_blocks = connection_manager.min_settle_blocks + 10
    wait_until_block(
        connection_manager.raiden.chain,
        before_block + wait_blocks
    )
    assert connection_manager.raiden.chain.block_number >= before_block + wait_blocks
    wait_until_block(
        receiver.chain,
        before_block + wait_blocks
    )
    while receiver_channel.state != CHANNEL_STATE_SETTLED:
        gevent.sleep(receiver.alarm.wait_time)
    after = len(connection_manager.receiving_channels)

    assert before > after
    assert after == 0
Exemple #23
0
def test_new_netting_contract(raiden_network, token_amount, settle_timeout):
    # pylint: disable=line-too-long,too-many-statements,too-many-locals

    app0, app1, app2 = raiden_network
    peer0_address = app0.raiden.address
    peer1_address = app1.raiden.address
    peer2_address = app2.raiden.address

    blockchain_service0 = app0.raiden.chain

    token_address = blockchain_service0.deploy_and_register_token(
        contract_name='HumanStandardToken',
        contract_file='HumanStandardToken.sol',
        constructor_parameters=(token_amount, 'raiden', 2, 'Rd'),
    )

    token0 = blockchain_service0.token(token_address)
    for transfer_to in raiden_network[1:]:
        token0.transfer(
            privatekey_to_address(transfer_to.raiden.privkey),
            token_amount // len(raiden_network),
        )

    manager0 = blockchain_service0.manager_by_token(token_address)

    # sanity
    assert manager0.channels_addresses() == []
    assert manager0.channels_by_participant(peer0_address) == []
    assert manager0.channels_by_participant(peer1_address) == []
    assert manager0.channels_by_participant(peer2_address) == []

    # create one channel
    netting_address_01 = manager0.new_netting_channel(
        peer0_address,
        peer1_address,
        settle_timeout,
    )

    # check contract state
    netting_channel_01 = blockchain_service0.netting_channel(
        netting_address_01)
    assert netting_channel_01.can_transfer() is False

    # check channels
    channel_list = manager0.channels_addresses()
    assert sorted(channel_list[0]) == sorted([peer0_address, peer1_address])

    assert manager0.channels_by_participant(peer0_address) == [
        netting_address_01
    ]
    assert manager0.channels_by_participant(peer1_address) == [
        netting_address_01
    ]
    assert manager0.channels_by_participant(peer2_address) == []
    # create a duplicated channel with same participants while previous channel
    #  is still open should throw an exception
    with pytest.raises(Exception):
        manager0.new_netting_channel(
            peer0_address,
            peer1_address,
            settle_timeout,
        )
    # create other channel
    netting_address_02 = manager0.new_netting_channel(
        peer0_address,
        peer2_address,
        settle_timeout,
    )

    netting_channel_02 = blockchain_service0.netting_channel(
        netting_address_02)

    assert netting_channel_02.can_transfer() is False

    channel_list = manager0.channels_addresses()
    expected_channels = [
        sorted([peer0_address, peer1_address]),
        sorted([peer0_address, peer2_address]),
    ]

    for channel in channel_list:
        assert sorted(channel) in expected_channels

    result0 = sorted(manager0.channels_by_participant(peer0_address))
    result1 = sorted([netting_address_01, netting_address_02])
    assert result0 == result1
    assert manager0.channels_by_participant(peer1_address) == [
        netting_address_01
    ]
    assert manager0.channels_by_participant(peer2_address) == [
        netting_address_02
    ]

    # deposit without approve should fail
    netting_channel_01.deposit(100)
    assert netting_channel_01.can_transfer() is False
    assert netting_channel_02.can_transfer() is False
    assert netting_channel_01.detail(None)['our_balance'] == 0
    assert netting_channel_02.detail(None)['our_balance'] == 0

    # single-funded channel
    app0.raiden.chain.token(token_address).approve(netting_address_01, 100)
    netting_channel_01.deposit(100)
    assert netting_channel_01.can_transfer() is True
    assert netting_channel_02.can_transfer() is False

    assert netting_channel_01.detail(None)['our_balance'] == 100
    assert netting_channel_02.detail(None)['our_balance'] == 0

    # double-funded channel
    app0.raiden.chain.token(token_address).approve(netting_address_02, 70)
    netting_channel_02.deposit(70)
    assert netting_channel_01.can_transfer() is True
    assert netting_channel_02.can_transfer() is True

    assert netting_channel_02.detail(None)['our_balance'] == 70
    assert netting_channel_02.detail(None)['partner_balance'] == 0

    app2.raiden.chain.token(token_address).approve(netting_address_02, 130)
    app2.raiden.chain.netting_channel(netting_address_02).deposit(130)
    assert netting_channel_01.can_transfer() is True
    assert netting_channel_02.can_transfer() is True

    assert netting_channel_02.detail(None)['our_balance'] == 70
    assert netting_channel_02.detail(None)['partner_balance'] == 130

    # open channel with same peer again after settling
    netting_channel_01.close(None)
    wait_until_block(app0.raiden.chain,
                     app0.raiden.chain.block_number() + settle_timeout + 1)
    netting_channel_01.settle()
    assert netting_channel_01.opened() is ''
    assert netting_channel_01.closed() != 0

    # open channel with same peer again
    netting_address_01_reopened = manager0.new_netting_channel(
        peer0_address,
        peer1_address,
        settle_timeout,
    )
    netting_channel_01_reopened = blockchain_service0.netting_channel(
        netting_address_01_reopened)

    assert netting_channel_01_reopened.opened() != 0
    assert netting_address_01_reopened in manager0.channels_by_participant(
        peer0_address)
    assert netting_address_01 not in manager0.channels_by_participant(
        peer0_address)

    app0.raiden.chain.token(token_address).approve(netting_address_01_reopened,
                                                   100)
    netting_channel_01_reopened.deposit(100)
    assert netting_channel_01_reopened.opened() != 0
Exemple #24
0
def test_automatic_dispute(raiden_network, deposit, settle_timeout):
    app0, app1 = raiden_network
    channel0 = app0.raiden.channelgraphs.values(
    )[0].partneraddress_channel.values()[0]
    channel1 = app1.raiden.channelgraphs.values(
    )[0].partneraddress_channel.values()[0]
    privatekey0 = app0.raiden.private_key
    privatekey1 = app1.raiden.private_key
    address0 = privatekey_to_address(privatekey0.secret)
    address1 = privatekey_to_address(privatekey1.secret)
    token = app0.raiden.chain.token(channel0.token_address)
    initial_balance0 = token.balance_of(address0)
    initial_balance1 = token.balance_of(address1)

    # Alice sends Bob 10 tokens
    amount_alice1 = 10
    identifier_alice1 = 1
    alice_first_transfer = channel0.create_directtransfer(
        amount_alice1,
        identifier_alice1,
    )
    alice_first_transfer.sign(privatekey0, address0)
    channel0.register_transfer(
        app0.raiden.get_block_number(),
        alice_first_transfer,
    )
    channel1.register_transfer(
        app1.raiden.get_block_number(),
        alice_first_transfer,
    )

    # Bob sends Alice 50 tokens
    amount_bob1 = 50
    identifier_bob1 = 1
    bob_first_transfer = channel1.create_directtransfer(
        amount_bob1,
        identifier_bob1,
    )
    bob_first_transfer.sign(privatekey1, address1)
    channel0.register_transfer(
        app0.raiden.get_block_number(),
        bob_first_transfer,
    )
    channel1.register_transfer(
        app1.raiden.get_block_number(),
        bob_first_transfer,
    )

    # Finally Alice sends Bob 60 tokens
    identifier_alice2 = 2
    amount_alice2 = 60
    alice_second_transfer = channel0.create_directtransfer(
        amount_alice2,
        identifier_alice2,
    )
    alice_second_transfer.sign(privatekey0, address0)
    channel0.register_transfer(
        app0.raiden.get_block_number(),
        alice_second_transfer,
    )
    channel1.register_transfer(
        app1.raiden.get_block_number(),
        alice_second_transfer,
    )

    bob_last_transaction = bob_first_transfer

    # Alice can only provide one of Bob's transfer, so she is incetivized to
    # use the one with the largest transferred_amount.
    channel0.external_state.close(bob_last_transaction)
    chain0 = app0.raiden.chain
    wait_until_block(chain0, chain0.block_number() + 1)

    assert channel0.external_state.close_event.wait(timeout=25)
    assert channel1.external_state.close_event.wait(timeout=25)

    assert channel0.external_state.closed_block != 0
    assert channel1.external_state.closed_block != 0

    # Bob needs to provide a transfer otherwise it's netted balance will be
    # wrong, so he is incetivized to use Alice's transfer with the largest
    # transferred_amount.
    channel1.external_state.update_transfer(alice_second_transfer, )

    # wait until the settle timeout has passed
    settle_expiration = chain0.block_number() + settle_timeout
    wait_until_block(chain0, settle_expiration)

    # the settle event must be set
    assert channel0.external_state.settle_event.wait(timeout=60)
    assert channel1.external_state.settle_event.wait(timeout=60)

    # check that the channel is properly settled and that Bob's client
    # automatically called updateTransfer() to reflect the actual transactions
    assert channel0.external_state.settled_block != 0
    assert channel1.external_state.settled_block != 0
    assert token.balance_of(
        channel0.external_state.netting_channel.address) == 0
    total_alice = amount_alice1 + amount_alice2
    total_bob = amount_bob1
    assert token.balance_of(
        address0) == initial_balance0 + deposit - total_alice + total_bob
    assert token.balance_of(
        address1) == initial_balance1 + deposit + total_alice - total_bob
def test_transfer_from_outdated(raiden_network, settle_timeout):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    graph0 = list(app0.raiden.token_to_channelgraph.values())[0]
    graph1 = list(app1.raiden.token_to_channelgraph.values())[0]

    channel0 = graph0.partneraddress_to_channel[app1.raiden.address]
    channel1 = graph1.partneraddress_to_channel[app0.raiden.address]

    balance0 = channel0.balance
    balance1 = channel1.balance

    assert graph0.token_address == graph1.token_address
    assert app1.raiden.address in graph0.partneraddress_to_channel

    amount = 10
    result = app0.raiden.direct_transfer_async(
        graph0.token_address,
        amount,
        target=app1.raiden.address,
        identifier=1,
    )

    assert result.wait(timeout=10)

    assert_synched_channels(
        channel0, balance0 - amount, [],
        channel1, balance1 + amount, []
    )

    channel1.external_state.close(channel1.our_state.balance_proof)

    wait_until_block(
        app1.raiden.chain,
        app1.raiden.chain.block_number() + 1
    )

    assert channel0.external_state.close_event.wait(timeout=25)
    assert channel1.external_state.close_event.wait(timeout=25)

    assert channel0.external_state.closed_block != 0
    assert channel1.external_state.closed_block != 0

    wait_until_block(
        app0.raiden.chain,
        app0.raiden.chain.block_number() + settle_timeout,
    )

    assert channel0.external_state.settle_event.wait(timeout=25)
    assert channel1.external_state.settle_event.wait(timeout=25)

    assert channel0.external_state.settled_block != 0
    assert channel1.external_state.settled_block != 0

    # and now receive one more transfer from the closed channel
    direct_transfer_message = DirectTransfer(
        identifier=1,
        nonce=1,
        token=graph0.token_address,
        channel=channel0.channel_address,
        transferred_amount=10,
        recipient=app0.raiden.address,
        locksroot=UNIT_HASHLOCK,
    )

    sign_and_send(
        direct_transfer_message,
        app1.raiden.private_key,
        app1.raiden.address,
        app1,
    )
Exemple #26
0
def test_participant_selection(raiden_network, token_addresses,
                               blockchain_type):
    token_address = token_addresses[0]

    # connect the first node (will register the token if necessary)
    RaidenAPI(raiden_network[0].raiden).connect_token_network(
        token_address, 100)

    # connect the other nodes
    connect_greenlets = [
        gevent.spawn(
            RaidenAPI(app.raiden).connect_token_network, token_address, 100)
        for app in raiden_network[1:]
    ]
    gevent.wait(connect_greenlets)

    # wait some blocks to let the network connect
    wait_blocks = 15
    for i in range(wait_blocks):
        for app in raiden_network:
            wait_until_block(app.raiden.chain,
                             app.raiden.chain.block_number() + 1)
        # tester needs an explicit context switch :(
        if blockchain_type == 'tester':
            gevent.sleep(1)

    connection_managers = [
        app.raiden.connection_manager_for_token(token_address)
        for app in raiden_network
    ]

    def open_channels_count(connection_managers_):
        return [
            connection_manager.open_channels
            for connection_manager in connection_managers_
        ]

    assert all(open_channels_count(connection_managers))

    def not_saturated(connection_managers):
        return [
            1 for connection_manager in connection_managers
            if connection_manager.open_channels <
            connection_manager.initial_channel_target
        ]

    chain = raiden_network[-1].raiden.chain
    max_wait = 12

    while len(not_saturated(connection_managers)) > 0 and max_wait > 0:
        wait_until_block(chain, chain.block_number() + 1)
        max_wait -= 1

    assert len(not_saturated(connection_managers)) == 0

    # Ensure unpartitioned network
    addresses = [app.raiden.address for app in raiden_network]
    for connection_manager in connection_managers:
        assert all(
            connection_manager.channelgraph.has_path(
                connection_manager.raiden.address, address)
            for address in addresses)

    # average channel count
    acc = (sum(
        len(connection_manager.open_channels)
        for connection_manager in connection_managers) /
           float(len(connection_managers)))

    try:
        # FIXME: depending on the number of channels, this will fail, due to weak
        # selection algorithm
        # https://github.com/raiden-network/raiden/issues/576
        assert not any(
            len(connection_manager.open_channels) > 2 * acc
            for connection_manager in connection_managers)
    except AssertionError:
        pass

    # test `leave()` method
    connection_manager = connection_managers[0]
    before = len(connection_manager.open_channels)

    RaidenAPI(raiden_network[0].raiden).leave_token_network(
        token_address, wait_for_settle=False)

    wait_until_block(connection_manager.raiden.chain,
                     (connection_manager.raiden.chain.block_number() +
                      connection_manager.raiden.config['settle_timeout'] + 1))
    after = len(connection_manager.open_channels)

    assert before > after
    assert after == 0
Exemple #27
0
def test_channel_lifecycle(raiden_network, token_addresses, deposit):
    node1, node2 = raiden_network
    token_address = token_addresses[0]

    api1 = RaidenAPI(node1.raiden)
    api2 = RaidenAPI(node2.raiden)

    # nodes don't have a channel, so they are not healthchecking
    assert api1.get_node_network_state(api2.address) == NODE_NETWORK_UNKNOWN
    assert api2.get_node_network_state(api1.address) == NODE_NETWORK_UNKNOWN
    assert not api1.get_channel_list(token_address, api2.address)

    # open is a synchronous api
    api1.channel_open(token_address, api2.address)
    channels = api1.get_channel_list(token_address, api2.address)
    assert len(channels) == 1

    channel12 = get_channelstate(node1, node2, token_address)
    assert channel.get_status(channel12) == CHANNEL_STATE_OPENED

    event_list1 = api1.get_channel_events(
        channel12.identifier,
        channel12.open_transaction.finished_block_number,
    )
    assert event_list1 == []

    # Load the new state with the deposit
    api1.channel_deposit(token_address, api2.address, deposit)
    channel12 = get_channelstate(node1, node2, token_address)

    assert channel.get_status(channel12) == CHANNEL_STATE_OPENED
    assert channel.get_balance(channel12.our_state,
                               channel12.partner_state) == deposit
    assert channel12.our_state.contract_balance == deposit
    assert api1.get_channel_list(token_address, api2.address) == [channel12]

    # there is a channel open, they must be healthchecking each other
    assert api1.get_node_network_state(api2.address) == NODE_NETWORK_REACHABLE
    assert api2.get_node_network_state(api1.address) == NODE_NETWORK_REACHABLE

    event_list2 = api1.get_channel_events(
        channel12.identifier,
        channel12.open_transaction.finished_block_number,
    )
    assert any((event['_event_type'] == b'ChannelNewBalance'
                and event['participant'] == address_encoder(api1.address))
               for event in event_list2)

    api1.channel_close(token_address, api2.address)
    node1.raiden.poll_blockchain_events()

    # Load the new state with the channel closed
    channel12 = get_channelstate(node1, node2, token_address)

    event_list3 = api1.get_channel_events(
        channel12.identifier,
        channel12.open_transaction.finished_block_number,
    )
    assert len(event_list3) > len(event_list2)
    assert any((event['_event_type'] == b'ChannelClosed'
                and event['closing_address'] == address_encoder(api1.address))
               for event in event_list3)
    assert channel.get_status(channel12) == CHANNEL_STATE_CLOSED

    settlement_block = (
        channel12.close_transaction.finished_block_number +
        channel12.settle_timeout +
        10  # arbitrary number of additional blocks, used to wait for the settle() call
    )
    wait_until_block(node1.raiden.chain, settlement_block)

    # Load the new state with the channel settled
    channel12 = get_channelstate(node1, node2, token_address)

    node1.raiden.poll_blockchain_events()
    assert channel.get_status(channel12) == CHANNEL_STATE_SETTLED
Exemple #28
0
def test_channel_lifecycle(blockchain_type, raiden_network, token_addresses,
                           deposit):
    if blockchain_type == 'tester':
        pytest.skip(
            'there is not support ATM for retrieving events from tester')

    node1, node2 = raiden_network
    token_address = token_addresses[0]

    api1 = RaidenAPI(node1.raiden)
    api2 = RaidenAPI(node2.raiden)

    # nodes don't have a channel, so they are not healthchecking
    assert api1.get_node_network_state(api2.address) == NODE_NETWORK_UNKNOWN
    assert api2.get_node_network_state(api1.address) == NODE_NETWORK_UNKNOWN
    assert api1.get_channel_list(token_address, api2.address) == []

    # this is a synchronous api
    api1.open(token_address, api2.address)
    channels = api1.get_channel_list(token_address, api2.address)
    assert len(channels) == 1
    channel12 = channels[0]

    event_list1 = api1.get_channel_events(
        channel12.channel_address,
        channel12.external_state.opened_block,
    )
    assert event_list1 == []

    # the channel has no deposit yet
    assert channel12.state == CHANNEL_STATE_OPENED

    api1.deposit(token_address, api2.address, deposit)

    assert channel12.state == CHANNEL_STATE_OPENED
    assert channel12.balance == deposit
    assert channel12.contract_balance == deposit
    assert api1.get_channel_list(token_address, api2.address) == [channel12]

    # there is a channel open, they must be healthchecking each other
    assert api1.get_node_network_state(api2.address) == NODE_NETWORK_REACHABLE
    assert api2.get_node_network_state(api1.address) == NODE_NETWORK_REACHABLE

    event_list2 = api1.get_channel_events(
        channel12.channel_address,
        channel12.external_state.opened_block,
    )
    assert any((event['_event_type'] == 'ChannelNewBalance'
                and event['participant'] == hexlify(api1.address))
               for event in event_list2)

    with pytest.raises(InvalidState):
        api1.settle(token_address, api2.address)

    api1.close(token_address, api2.address)
    node1.raiden.poll_blockchain_events()

    event_list3 = api1.get_channel_events(
        channel12.channel_address,
        channel12.external_state.opened_block,
    )
    assert len(event_list3) > len(event_list2)
    assert any((event['_event_type'] == 'ChannelClosed'
                and event['closing_address'] == hexlify(api1.address))
               for event in event_list3)
    assert channel12.state == CHANNEL_STATE_CLOSED

    settlement_block = (
        channel12.external_state.closed_block + channel12.settle_timeout +
        5  # arbitrary number of additional blocks, used to wait for the settle() call
    )
    wait_until_block(node1.raiden.chain, settlement_block)

    node1.raiden.poll_blockchain_events()
    assert channel12.state == CHANNEL_STATE_SETTLED
Exemple #29
0
def test_automatic_dispute(raiden_network, deposit, settle_timeout,
                           reveal_timeout):
    app0, app1 = raiden_network
    channel0 = app0.raiden.managers_by_token_address.values(
    )[0].partneraddress_channel.values()[0]
    channel1 = app1.raiden.managers_by_token_address.values(
    )[0].partneraddress_channel.values()[0]
    privatekey0 = app0.raiden.private_key
    privatekey1 = app1.raiden.private_key
    address0 = privatekey_to_address(privatekey0.private_key)
    address1 = privatekey_to_address(privatekey1.private_key)
    token = app0.raiden.chain.token(channel0.token_address)
    initial_balance0 = token.balance_of(address0)
    initial_balance1 = token.balance_of(address1)

    # Alice sends Bob 10 tokens
    amount_alice1 = 10
    direct_transfer = channel0.create_directtransfer(
        amount_alice1,
        1  # TODO: fill in identifier
    )
    direct_transfer.sign(privatekey0, address0)
    channel0.register_transfer(direct_transfer)
    channel1.register_transfer(direct_transfer)
    alice_old_transaction = direct_transfer

    # Bob sends Alice 50 tokens
    amount_bob1 = 50
    direct_transfer = channel1.create_directtransfer(
        amount_bob1,
        1  # TODO: fill in identifier
    )
    direct_transfer.sign(privatekey1, address1)
    channel0.register_transfer(direct_transfer)
    channel1.register_transfer(direct_transfer)
    bob_last_transaction = direct_transfer

    # Finally Alice sends Bob 60 tokens
    amount_alice2 = 60
    direct_transfer = channel0.create_directtransfer(
        amount_alice2,
        1  # TODO: fill in identifier
    )
    direct_transfer.sign(privatekey0, address0)
    channel0.register_transfer(direct_transfer)
    channel1.register_transfer(direct_transfer)

    # Then Alice attempts to close the channel with an older transfer of hers
    channel0.external_state.close(
        None,
        bob_last_transaction,
    )
    chain0 = app0.raiden.chain
    wait_until_block(chain0, chain0.block_number() + 1)

    assert channel0.close_event.wait(timeout=25)
    assert channel1.close_event.wait(timeout=25)

    assert channel0.external_state.closed_block != 0
    assert channel1.external_state.closed_block != 0

    channel1.external_state.update_transfer(
        None,
        direct_transfer,
    )

    # wait until the settle timeout has passed
    settle_expiration = chain0.block_number() + settle_timeout
    wait_until_block(chain0, settle_expiration)

    # the settle event must be set
    assert channel0.settle_event.wait(timeout=60)
    assert channel1.settle_event.wait(timeout=60)

    # check that the channel is properly settled and that Bob's client
    # automatically called updateTransfer() to reflect the actual transactions
    assert channel0.external_state.settled_block != 0
    assert channel1.external_state.settled_block != 0
    assert token.balance_of(
        channel0.external_state.netting_channel.address) == 0
    total_alice = amount_alice1 + amount_alice2
    total_bob = amount_bob1
    assert token.balance_of(
        address0) == initial_balance0 + deposit - total_alice + total_bob
    assert token.balance_of(
        address1) == initial_balance1 + deposit + total_alice - total_bob
Exemple #30
0
def test_settlement(raiden_network, settle_timeout, reveal_timeout):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    setup_messages_cb()

    asset_manager0 = app0.raiden.managers_by_asset_address.values()[0]
    asset_manager1 = app1.raiden.managers_by_asset_address.values()[0]

    chain0 = app0.raiden.chain

    channel0 = asset_manager0.partneraddress_channel[app1.raiden.address]
    channel1 = asset_manager1.partneraddress_channel[app0.raiden.address]

    balance0 = channel0.balance
    balance1 = channel1.balance

    amount = 10
    expiration = app0.raiden.chain.block_number() + reveal_timeout + 1
    secret = 'secret'
    hashlock = sha3(secret)

    assert app1.raiden.address in asset_manager0.partneraddress_channel
    assert asset_manager0.asset_address == asset_manager1.asset_address

    nettingaddress0 = channel0.external_state.netting_channel.address
    nettingaddress1 = channel1.external_state.netting_channel.address
    assert nettingaddress0 == nettingaddress1

    identifier = 1
    fee = 0
    transfermessage = channel0.create_mediatedtransfer(
        app0.raiden.address,
        app1.raiden.address,
        fee,
        amount,
        identifier,
        expiration,
        hashlock,
    )
    app0.raiden.sign(transfermessage)
    channel0.register_transfer(transfermessage)
    channel1.register_transfer(transfermessage)

    assert_synched_channels(
        channel0,
        balance0,
        [],
        channel1,
        balance1,
        [transfermessage.lock],
    )

    # At this point we are assuming the following:
    #
    #    A -> B MediatedTransfer
    #    B -> A SecretRequest
    #    A -> B RevealSecret
    #    - protocol didn't continue
    #
    # B knowns the secret but doesn't have an updated balance proof, B needs to
    # call settle.

    # get proof, that locked transfermessage was in merkle tree, with locked.root
    lock = channel1.our_state.balance_proof.get_lock_by_hashlock(hashlock)
    unlock_proof = channel1.our_state.balance_proof.compute_proof_for_lock(
        secret, lock)

    root = channel1.our_state.balance_proof.merkleroot_for_unclaimed()

    assert check_proof(
        unlock_proof.merkle_proof,
        root,
        sha3(transfermessage.lock.as_bytes),
    )
    assert unlock_proof.lock_encoded == transfermessage.lock.as_bytes
    assert unlock_proof.secret == secret

    # a ChannelClose event will be generated, this will be polled by both apps
    # and each must start a task for calling settle
    channel0.external_state.netting_channel.close(
        app0.raiden.address,
        transfermessage,
        None,
    )

    # unlock will not be called by Channel.channel_closed because we did not
    # register the secret
    channel0.external_state.netting_channel.unlock(
        app0.raiden.address,
        [unlock_proof],
    )

    settle_expiration = chain0.block_number() + settle_timeout
    wait_until_block(chain0, settle_expiration)

    # settle must be called by the apps triggered by the ChannelClose event,
    # and the channels must update it's state based on the ChannelSettled event
    assert channel0.external_state.settled_block != 0
    assert channel1.external_state.settled_block != 0
def test_start_end_attack(asset_address, raiden_chain, deposit):
    """ An attacker can try to steal assets from a hub or the last node in a
    path.

    The attacker needs to use two addresses (A1 and A2) and connect both to the
    hub H, once connected a mediated transfer is initialized from A1 to A2
    through H, once the node A2 receives the mediated transfer the attacker
    uses the it's know secret and reveal to close and settles the channel H-A2,
    without revealing the secret to H's raiden node.

    The intention is to make the hub transfer the asset but for him to be
    unable to require the asset A1.
    """
    amount = 30

    asset = asset_address[0]
    app0, app1, app2 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking

    # the attacker owns app0 and app2 and creates a transfer throught app1
    secret = pending_mediated_transfer(
        raiden_chain,
        asset,
        amount,
        1  # TODO: fill in identifier
    )
    hashlock = sha3(secret)

    attack_channel = channel(app2, app1, asset)
    attack_transfer = get_received_transfer(attack_channel, 0)
    attack_contract = attack_channel.external_state.netting_channel.address
    hub_contract = channel(app1, app0, asset).external_state.netting_channel.address

    # the attacker can create a merkle proof of the locked transfer
    lock = attack_channel.our_state.balance_proof.get_lock_by_hashlock(hashlock)
    unlock_proof = attack_channel.our_state.balance_proof.compute_proof_for_lock(secret, lock)

    # start the settle counter
    attack_channel.netting_channel.close(
        app2.raiden.address,
        attack_transfer,
        None
    )

    # wait until the last block to reveal the secret, hopefully we are not
    # missing a block during the test
    wait_until_block(app2.raiden.chain, attack_transfer.lock.expiration - 1)

    # since the attacker knows the secret he can net the lock
    attack_channel.netting_channel.unlock(
        [(unlock_proof, attack_transfer.lock, secret)],
    )
    # XXX: verify that the secret was publicized

    # at this point the hub might not know yet the secret, and won't be able to
    # claim the asset from the channel A1 - H

    # the attacker settle the contract
    app2.raiden.chain.next_block()

    attack_channel.netting_channel.settle(asset, attack_contract)

    # at this point the attack has the "stolen" funds
    attack_contract = app2.raiden.chain.asset_hashchannel[asset][attack_contract]
    assert attack_contract.participants[app2.raiden.address]['netted'] == deposit + amount
    assert attack_contract.participants[app1.raiden.address]['netted'] == deposit - amount

    # and the hub's channel A1-H doesn't
    hub_contract = app1.raiden.chain.asset_hashchannel[asset][hub_contract]
    assert hub_contract.participants[app0.raiden.address]['netted'] == deposit
    assert hub_contract.participants[app1.raiden.address]['netted'] == deposit

    # to mitigate the attack the Hub _needs_ to use a lower expiration for the
    # locked transfer between H-A2 than A1-H, since for A2 to acquire the asset
    # it needs to make the secret public in the block chain we publish the
    # secret through an event and the Hub will be able to require it's funds
    app1.raiden.chain.next_block()

    # XXX: verify that the Hub has found the secret, close and settle the channel

    # the hub has acquired it's asset
    hub_contract = app1.raiden.chain.asset_hashchannel[asset][hub_contract]
    assert hub_contract.participants[app0.raiden.address]['netted'] == deposit + amount
    assert hub_contract.participants[app1.raiden.address]['netted'] == deposit - amount
Exemple #32
0
def test_start_end_attack(token_addresses, raiden_chain, deposit):
    """ An attacker can try to steal tokens from a hub or the last node in a
    path.

    The attacker needs to use two addresses (A1 and A2) and connect both to the
    hub H. Once connected a mediated transfer is initialized from A1 to A2
    through H. Once the node A2 receives the mediated transfer the attacker
    uses the known secret and reveal to close and settle the channel H-A2,
    without revealing the secret to H's raiden node.

    The intention is to make the hub transfer the token but for him to be
    unable to require the token A1."""
    amount = 30

    token = token_addresses[0]
    app0, app1, app2 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_registry.address,
        token,
    )

    # the attacker owns app0 and app2 and creates a transfer through app1
    identifier = 1
    secret = pending_mediated_transfer(
        raiden_chain,
        token_network_identifier,
        amount,
        identifier,
    )
    secrethash = sha3(secret)

    attack_channel = get_channelstate(app2, app1, token_network_identifier)
    attack_transfer = None  # TODO
    attack_contract = attack_channel.external_state.netting_channel.address
    hub_contract = (
        get_channelstate(app1, app0, token_network_identifier)
        .external_state
        .netting_channel.address
    )

    # the attacker can create a merkle proof of the locked transfer
    lock = attack_channel.partner_state.get_lock_by_secrethash(secrethash)
    unlock_proof = attack_channel.partner_state.compute_proof_for_lock(secret, lock)

    # start the settle counter
    attack_balance_proof = attack_transfer.to_balanceproof()
    attack_channel.netting_channel.channel_close(attack_balance_proof)

    # wait until the last block to reveal the secret, hopefully we are not
    # missing a block during the test
    wait_until_block(app2.raiden.chain, attack_transfer.lock.expiration - 1)

    # since the attacker knows the secret he can net the lock
    attack_channel.netting_channel.unlock(
        UnlockProofState(unlock_proof, attack_transfer.lock, secret),
    )
    # XXX: verify that the secret was publicized

    # at this point the hub might not know the secret yet, and won't be able to
    # claim the token from the channel A1 - H

    # the attacker settles the contract
    app2.raiden.chain.next_block()

    attack_channel.netting_channel.settle(token, attack_contract)

    # at this point the attacker has the "stolen" funds
    attack_contract = app2.raiden.chain.token_hashchannel[token][attack_contract]
    assert attack_contract.participants[app2.raiden.address]['netted'] == deposit + amount
    assert attack_contract.participants[app1.raiden.address]['netted'] == deposit - amount

    # and the hub's channel A1-H doesn't
    hub_contract = app1.raiden.chain.token_hashchannel[token][hub_contract]
    assert hub_contract.participants[app0.raiden.address]['netted'] == deposit
    assert hub_contract.participants[app1.raiden.address]['netted'] == deposit

    # to mitigate the attack the Hub _needs_ to use a lower expiration for the
    # locked transfer between H-A2 than A1-H. For A2 to acquire the token
    # it needs to make the secret public in the blockchain so it publishes the
    # secret through an event and the Hub is able to require its funds
    app1.raiden.chain.next_block()

    # XXX: verify that the Hub has found the secret, close and settle the channel

    # the hub has acquired its token
    hub_contract = app1.raiden.chain.token_hashchannel[token][hub_contract]
    assert hub_contract.participants[app0.raiden.address]['netted'] == deposit + amount
    assert hub_contract.participants[app1.raiden.address]['netted'] == deposit - amount
Exemple #33
0
def test_query_events(raiden_chain, token_addresses, deposit, settle_timeout,
                      events_poll_timeout):
    app0, app1 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking
    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        registry_address,
        token_address,
    )

    manager0 = app0.raiden.default_registry.manager_by_token(token_address)

    channelcount0 = views.total_token_network_channels(
        views.state_from_app(app0),
        registry_address,
        token_address,
    )

    events = get_all_registry_events(
        app0.raiden.chain,
        registry_address,
        events=ALL_EVENTS,
        from_block=0,
        to_block='latest',
    )

    assert len(events) == 1
    assert events[0]['event'] == EVENT_TOKEN_ADDED
    assert event_dicts_are_equal(
        events[0]['args'], {
            'registry_address': to_normalized_address(registry_address),
            'channel_manager_address': to_normalized_address(manager0.address),
            'token_address': to_normalized_address(token_address),
            'block_number': 'ignore',
        })

    events = get_all_registry_events(
        app0.raiden.chain,
        app0.raiden.default_registry.address,
        events=ALL_EVENTS,
        from_block=999999998,
        to_block=999999999,
    )
    assert not events

    channel_address = RaidenAPI(app0.raiden).channel_open(
        registry_address,
        token_address,
        app1.raiden.address,
    )

    gevent.sleep(events_poll_timeout * 2)

    events = get_all_channel_manager_events(
        app0.raiden.chain,
        manager0.address,
        events=ALL_EVENTS,
        from_block=0,
        to_block='latest',
    )

    assert len(events) == 1
    assert events[0]['event'] == EVENT_CHANNEL_NEW
    assert event_dicts_are_equal(
        events[0]['args'], {
            'registry_address': to_normalized_address(registry_address),
            'settle_timeout': settle_timeout,
            'netting_channel': to_normalized_address(channel_address),
            'participant1': to_normalized_address(app0.raiden.address),
            'participant2': to_normalized_address(app1.raiden.address),
            'block_number': 'ignore',
        })

    events = get_all_channel_manager_events(
        app0.raiden.chain,
        manager0.address,
        events=ALL_EVENTS,
        from_block=999999998,
        to_block=999999999,
    )
    assert not events

    # channel is created but not opened and without funds
    channelcount1 = views.total_token_network_channels(
        views.state_from_app(app0),
        registry_address,
        token_address,
    )
    assert channelcount0 + 1 == channelcount1

    assert_synched_channel_state(
        token_network_identifier,
        app0,
        0,
        [],
        app1,
        0,
        [],
    )

    RaidenAPI(app0.raiden).set_total_channel_deposit(
        registry_address,
        token_address,
        app1.raiden.address,
        deposit,
    )

    gevent.sleep(events_poll_timeout * 2)

    all_netting_channel_events = get_all_netting_channel_events(
        app0.raiden.chain,
        channel_address,
        from_block=0,
        to_block='latest',
    )

    events = get_all_netting_channel_events(
        app0.raiden.chain,
        channel_address,
        events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_NEW_BALANCE)],
    )

    assert len(all_netting_channel_events) == 1
    assert len(events) == 1

    assert events[0]['event'] == EVENT_CHANNEL_NEW_BALANCE
    new_balance_event = {
        'registry_address': to_normalized_address(registry_address),
        'token_address': to_normalized_address(token_address),
        'participant': to_normalized_address(app0.raiden.address),
        'balance': deposit,
        'block_number': 'ignore',
    }

    assert event_dicts_are_equal(all_netting_channel_events[-1]['args'],
                                 new_balance_event)
    assert event_dicts_are_equal(events[0]['args'], new_balance_event)

    RaidenAPI(app0.raiden).channel_close(
        registry_address,
        token_address,
        app1.raiden.address,
    )

    gevent.sleep(events_poll_timeout * 2)

    all_netting_channel_events = get_all_netting_channel_events(
        app0.raiden.chain,
        netting_channel_address=channel_address,
        from_block=0,
        to_block='latest',
    )

    events = get_all_netting_channel_events(
        app0.raiden.chain,
        channel_address,
        events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_CLOSED)],
    )

    assert len(all_netting_channel_events) == 2
    assert len(events) == 1

    assert events[0]['event'] == EVENT_CHANNEL_CLOSED
    closed_event = {
        'registry_address': to_normalized_address(registry_address),
        'closing_address': to_normalized_address(app0.raiden.address),
        'block_number': 'ignore',
    }

    assert event_dicts_are_equal(all_netting_channel_events[-1]['args'],
                                 closed_event)
    assert event_dicts_are_equal(events[0]['args'], closed_event)

    settle_expiration = app0.raiden.chain.block_number() + settle_timeout + 5
    wait_until_block(app0.raiden.chain, settle_expiration)

    all_netting_channel_events = get_all_netting_channel_events(
        app0.raiden.chain,
        netting_channel_address=channel_address,
        from_block=0,
        to_block='latest',
    )

    events = get_all_netting_channel_events(
        app0.raiden.chain,
        channel_address,
        events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_SETTLED)],
    )

    assert len(all_netting_channel_events) == 3
    assert len(events) == 1

    assert events[0]['event'] == EVENT_CHANNEL_SETTLED
    settled_event = {
        'registry_address': to_normalized_address(registry_address),
        'block_number': 'ignore',
    }

    assert event_dicts_are_equal(all_netting_channel_events[-1]['args'],
                                 settled_event)
    assert event_dicts_are_equal(events[0]['args'], settled_event)
def test_new_netting_contract(raiden_network, token_amount, settle_timeout):
    # pylint: disable=line-too-long,too-many-statements,too-many-locals

    app0, app1, app2 = raiden_network
    peer0_address = app0.raiden.address
    peer1_address = app1.raiden.address
    peer2_address = app2.raiden.address

    blockchain_service0 = app0.raiden.chain
    registry = app0.raiden.default_registry

    humantoken_path = get_contract_path('HumanStandardToken.sol')
    token_address = blockchain_service0.deploy_and_register_token(
        registry,
        contract_name='HumanStandardToken',
        contract_path=humantoken_path,
        constructor_parameters=(token_amount, 'raiden', 2, 'Rd'),
    )

    token0 = blockchain_service0.token(token_address)
    for transfer_to in raiden_network[1:]:
        token0.transfer(
            privatekey_to_address(transfer_to.raiden.privkey),
            token_amount // len(raiden_network),
        )

    manager0 = registry.manager_by_token(token_address)

    # sanity
    assert manager0.channels_addresses() == []
    assert manager0.channels_by_participant(peer0_address) == []
    assert manager0.channels_by_participant(peer1_address) == []
    assert manager0.channels_by_participant(peer2_address) == []

    # create one channel
    netting_address_01 = manager0.new_netting_channel(
        peer1_address,
        settle_timeout,
    )

    # check contract state
    netting_channel_01 = blockchain_service0.netting_channel(netting_address_01)
    assert netting_channel_01.can_transfer() is False

    # check channels
    channel_list = manager0.channels_addresses()
    assert sorted(channel_list[0]) == sorted([peer0_address, peer1_address])

    assert manager0.channels_by_participant(peer0_address) == [netting_address_01]
    assert manager0.channels_by_participant(peer1_address) == [netting_address_01]
    assert manager0.channels_by_participant(peer2_address) == []
    # create a duplicated channel with same participants while previous channel
    #  is still open should throw an exception
    with pytest.raises(Exception):
        manager0.new_netting_channel(
            peer1_address,
            settle_timeout,
        )
    # create other channel
    netting_address_02 = manager0.new_netting_channel(
        peer2_address,
        settle_timeout,
    )

    netting_channel_02 = blockchain_service0.netting_channel(netting_address_02)

    assert netting_channel_02.can_transfer() is False

    channel_list = manager0.channels_addresses()
    expected_channels = [
        sorted([peer0_address, peer1_address]),
        sorted([peer0_address, peer2_address]),
    ]

    for channel in channel_list:
        assert sorted(channel) in expected_channels

    result0 = sorted(manager0.channels_by_participant(peer0_address))
    result1 = sorted([netting_address_01, netting_address_02])
    assert result0 == result1
    assert manager0.channels_by_participant(peer1_address) == [netting_address_01]
    assert manager0.channels_by_participant(peer2_address) == [netting_address_02]

    # deposit without approve should fail
    netting_channel_01.deposit(100)
    assert netting_channel_01.can_transfer() is False
    assert netting_channel_02.can_transfer() is False
    assert netting_channel_01.detail()['our_balance'] == 0
    assert netting_channel_02.detail()['our_balance'] == 0

    # single-funded channel
    app0.raiden.chain.token(token_address).approve(netting_address_01, 100)
    netting_channel_01.deposit(100)
    assert netting_channel_01.can_transfer() is True
    assert netting_channel_02.can_transfer() is False

    assert netting_channel_01.detail()['our_balance'] == 100
    assert netting_channel_02.detail()['our_balance'] == 0

    # double-funded channel
    app0.raiden.chain.token(token_address).approve(netting_address_02, 70)
    netting_channel_02.deposit(70)
    assert netting_channel_01.can_transfer() is True
    assert netting_channel_02.can_transfer() is True

    assert netting_channel_02.detail()['our_balance'] == 70
    assert netting_channel_02.detail()['partner_balance'] == 0

    app2.raiden.chain.token(token_address).approve(netting_address_02, 130)
    app2.raiden.chain.netting_channel(netting_address_02).deposit(130)
    assert netting_channel_01.can_transfer() is True
    assert netting_channel_02.can_transfer() is True

    assert netting_channel_02.detail()['our_balance'] == 70
    assert netting_channel_02.detail()['partner_balance'] == 130

    # open channel with same peer again after settling
    netting_channel_01.close(
        nonce=0,
        transferred_amount=0,
        locksroot='',
        extra_hash='',
        signature='',
    )

    wait_until_block(app0.raiden.chain, app0.raiden.chain.block_number() + settle_timeout + 1)
    netting_channel_01.settle()

    with pytest.raises(AddressWithoutCode):
        netting_channel_01.closed()

    with pytest.raises(AddressWithoutCode):
        netting_channel_01.opened()

    # open channel with same peer again
    netting_address_01_reopened = manager0.new_netting_channel(
        peer1_address,
        settle_timeout,
    )
    netting_channel_01_reopened = blockchain_service0.netting_channel(netting_address_01_reopened)

    assert netting_channel_01_reopened.opened() != 0
    assert netting_address_01_reopened in manager0.channels_by_participant(peer0_address)
    assert netting_address_01 not in manager0.channels_by_participant(peer0_address)

    app0.raiden.chain.token(token_address).approve(netting_address_01_reopened, 100)
    netting_channel_01_reopened.deposit(100)
    assert netting_channel_01_reopened.opened() != 0
Exemple #35
0
def test_participant_selection(raiden_network, token_addresses):
    # pylint: disable=too-many-locals
    token_address = token_addresses[0]

    # connect the first node (will register the token if necessary)
    RaidenAPI(raiden_network[0].raiden).token_network_connect(
        token_address, 100)

    # connect the other nodes
    connect_greenlets = [
        gevent.spawn(
            RaidenAPI(app.raiden).token_network_connect, token_address, 100)
        for app in raiden_network[1:]
    ]
    gevent.wait(connect_greenlets)

    # wait some blocks to let the network connect
    wait_blocks = 15
    for _ in range(wait_blocks):
        for app in raiden_network:
            wait_until_block(app.raiden.chain,
                             app.raiden.chain.block_number() + 1)

    connection_managers = [
        app.raiden.connection_manager_for_token(token_address)
        for app in raiden_network
    ]

    def open_channels_count(connection_managers_):
        return [
            connection_manager.open_channels
            for connection_manager in connection_managers_
        ]

    assert all(open_channels_count(connection_managers))

    def not_saturated(connection_managers_):
        return [
            1 for connection_manager_ in connection_managers_
            if len(connection_manager_.open_channels) <
            connection_manager_.initial_channel_target
        ]

    chain = raiden_network[-1].raiden.chain
    max_wait = 12

    while not_saturated(connection_managers) and max_wait > 0:
        wait_until_block(chain, chain.block_number() + 1)
        max_wait -= 1

    assert not not_saturated(connection_managers)

    # Ensure unpartitioned network
    addresses = [app.raiden.address for app in raiden_network]
    for connection_manager in connection_managers:
        assert all(
            connection_manager.channelgraph.has_path(
                connection_manager.raiden.address, address)
            for address in addresses)

    # average channel count
    acc = (sum(
        len(connection_manager.open_channels)
        for connection_manager in connection_managers) /
           len(connection_managers))

    try:
        # FIXME: depending on the number of channels, this will fail, due to weak
        # selection algorithm
        # https://github.com/raiden-network/raiden/issues/576
        assert not any(
            len(connection_manager.open_channels) > 2 * acc
            for connection_manager in connection_managers)
    except AssertionError:
        pass

    # create a transfer to the leaving node, so we have a channel to settle
    sender = raiden_network[-1].raiden
    receiver = raiden_network[0].raiden

    # assert there is a direct channel receiver -> sender (vv)
    receiver_channel = RaidenAPI(receiver).get_channel_list(
        token_address=token_address, partner_address=sender.address)
    assert len(receiver_channel) == 1
    receiver_channel = receiver_channel[0]
    assert receiver_channel.external_state.opened_block != 0
    assert not receiver_channel.received_transfers

    # assert there is a direct channel sender -> receiver
    sender_channel = RaidenAPI(sender).get_channel_list(
        token_address=token_address, partner_address=receiver.address)
    assert len(sender_channel) == 1
    sender_channel = sender_channel[0]
    assert sender_channel.can_transfer
    assert sender_channel.external_state.opened_block != 0

    RaidenAPI(sender).transfer_and_wait(token_address, 1, receiver.address)

    # now receiver has a transfer
    assert len(receiver_channel.received_transfers)

    # test `leave()` method
    connection_manager = connection_managers[0]
    before = len(connection_manager.receiving_channels)

    timeout = (connection_manager.min_settle_blocks *
               connection_manager.raiden.chain.estimate_blocktime() * 5)

    assert timeout > 0
    with gevent.timeout.Timeout(timeout):
        try:
            RaidenAPI(
                raiden_network[0].raiden).token_network_leave(token_address)
        except gevent.timeout.Timeout:
            log.error('timeout while waiting for leave')

    before_block = connection_manager.raiden.chain.block_number()
    wait_blocks = connection_manager.min_settle_blocks + 10
    wait_until_block(connection_manager.raiden.chain,
                     before_block + wait_blocks)
    assert connection_manager.raiden.chain.block_number >= before_block + wait_blocks
    wait_until_block(receiver.chain, before_block + wait_blocks)
    while receiver_channel.state != CHANNEL_STATE_SETTLED:
        gevent.sleep(receiver.alarm.wait_time)
    after = len(connection_manager.receiving_channels)

    assert before > after
    assert after == 0
Exemple #36
0
def test_settled_lock(token_addresses, raiden_network, settle_timeout,
                      reveal_timeout):
    """ Any transfer following a secret revealed must update the locksroot, so
    that an attacker cannot reuse a secret to double claim a lock.
    """
    token = token_addresses[0]
    amount = 30

    app0, app1, app2, _ = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    address0 = app0.raiden.address
    address1 = app1.raiden.address

    forward_channel = channel(app0, app1, token)
    back_channel = channel(app1, app0, token)

    deposit0 = forward_channel.contract_balance
    deposit1 = back_channel.contract_balance

    token_contract = app0.raiden.chain.token(token)
    balance0 = token_contract.balance_of(address0)
    balance1 = token_contract.balance_of(address1)

    # mediated transfer
    identifier = 1
    expiration = app0.raiden.chain.block_number(
    ) + settle_timeout - reveal_timeout
    secret = pending_mediated_transfer(
        raiden_network,
        token,
        amount,
        identifier,
        expiration,
    )
    hashlock = sha3(secret)

    # get a proof for the pending transfer
    secret_transfer = get_received_transfer(back_channel, 0)
    lock = back_channel.our_state.balance_proof.get_lock_by_hashlock(hashlock)
    unlock_proof = back_channel.our_state.balance_proof.compute_proof_for_lock(
        secret, lock)

    # reveal the secret
    claim_lock(raiden_network, token, secret)

    # a new transfer to update the hashlock
    direct_transfer(app0, app1, token, amount)

    last_transfer = get_sent_transfer(forward_channel, 1)

    # call close giving the secret for a transfer that has being revealed
    back_channel.external_state.netting_channel.close(last_transfer)

    # check that the double unlock will fail
    with pytest.raises(Exception):
        back_channel.external_state.netting_channel.withdraw(
            [(unlock_proof, secret_transfer.lock.as_bytes, secret)], )

    # forward the block number to allow settle
    settle_expiration = app2.raiden.chain.block_number() + settle_timeout
    wait_until_block(app2.raiden.chain, settle_expiration)

    back_channel.external_state.netting_channel.settle()

    assert token_contract.balance_of(
        address0) == balance0 + deposit0 - amount * 2
    assert token_contract.balance_of(
        address1) == balance1 + deposit1 + amount * 2
Exemple #37
0
def test_start_end_attack(token_addresses, raiden_chain, deposit,
                          reveal_timeout):
    """ An attacker can try to steal tokens from a hub or the last node in a
    path.

    The attacker needs to use two addresses (A1 and A2) and connect both to the
    hub H, once connected a mediated transfer is initialized from A1 to A2
    through H, once the node A2 receives the mediated transfer the attacker
    uses the known secret and reveal to close and settles the channel H-A2,
    without revealing the secret to H's raiden node.

    The intention is to make the hub transfer the token but for him to be
    unable to require the token A1.
    """
    amount = 30

    token = token_addresses[0]
    app0, app1, app2 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking

    # the attacker owns app0 and app2 and creates a transfer through app1
    identifier = 1
    expiration = reveal_timeout + 5
    secret = pending_mediated_transfer(raiden_chain, token, amount, identifier,
                                       expiration)
    hashlock = sha3(secret)

    attack_channel = channel(app2, app1, token)
    attack_transfer = get_received_transfer(attack_channel, 0)
    attack_contract = attack_channel.external_state.netting_channel.address
    hub_contract = channel(app1, app0,
                           token).external_state.netting_channel.address

    # the attacker can create a merkle proof of the locked transfer
    lock = attack_channel.our_state.balance_proof.get_lock_by_hashlock(
        hashlock)
    unlock_proof = attack_channel.our_state.balance_proof.compute_proof_for_lock(
        secret, lock)

    # start the settle counter
    attack_channel.netting_channel.close(attack_transfer)

    # wait until the last block to reveal the secret, hopefully we are not
    # missing a block during the test
    wait_until_block(app2.raiden.chain, attack_transfer.lock.expiration - 1)

    # since the attacker knows the secret he can net the lock
    attack_channel.netting_channel.withdraw(
        [(unlock_proof, attack_transfer.lock, secret)], )
    # XXX: verify that the secret was publicized

    # at this point the hub might not know yet the secret, and won't be able to
    # claim the token from the channel A1 - H

    # the attacker settle the contract
    app2.raiden.chain.next_block()

    attack_channel.netting_channel.settle(token, attack_contract)

    # at this point the attack has the "stolen" funds
    attack_contract = app2.raiden.chain.token_hashchannel[token][
        attack_contract]
    assert attack_contract.participants[
        app2.raiden.address]['netted'] == deposit + amount
    assert attack_contract.participants[
        app1.raiden.address]['netted'] == deposit - amount

    # and the hub's channel A1-H doesn't
    hub_contract = app1.raiden.chain.token_hashchannel[token][hub_contract]
    assert hub_contract.participants[app0.raiden.address]['netted'] == deposit
    assert hub_contract.participants[app1.raiden.address]['netted'] == deposit

    # to mitigate the attack the Hub _needs_ to use a lower expiration for the
    # locked transfer between H-A2 than A1-H, since for A2 to acquire the token
    # it needs to make the secret public in the block chain we publish the
    # secret through an event and the Hub will be able to require it's funds
    app1.raiden.chain.next_block()

    # XXX: verify that the Hub has found the secret, close and settle the channel

    # the hub has acquired its token
    hub_contract = app1.raiden.chain.token_hashchannel[token][hub_contract]
    assert hub_contract.participants[
        app0.raiden.address]['netted'] == deposit + amount
    assert hub_contract.participants[
        app1.raiden.address]['netted'] == deposit - amount
def test_settlement(raiden_network, settle_timeout, reveal_timeout):
    alice_app, bob_app = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    setup_messages_cb()

    alice_graph = list(alice_app.raiden.token_to_channelgraph.values())[0]
    bob_graph = list(bob_app.raiden.token_to_channelgraph.values())[0]
    assert alice_graph.token_address == bob_graph.token_address

    alice_bob_channel = alice_graph.partneraddress_to_channel[bob_app.raiden.address]
    bob_alice_channel = bob_graph.partneraddress_to_channel[alice_app.raiden.address]

    alice_deposit = alice_bob_channel.balance
    bob_deposit = bob_alice_channel.balance

    token = alice_app.raiden.chain.token(alice_bob_channel.token_address)

    alice_balance = token.balance_of(alice_app.raiden.address)
    bob_balance = token.balance_of(bob_app.raiden.address)

    alice_chain = alice_app.raiden.chain

    alice_to_bob_amount = 10
    expiration = alice_app.raiden.chain.block_number() + reveal_timeout + 1
    secret = b'secretsecretsecretsecretsecretse'
    hashlock = sha3(secret)

    assert bob_app.raiden.address in alice_graph.partneraddress_to_channel

    nettingaddress0 = alice_bob_channel.external_state.netting_channel.address
    nettingaddress1 = bob_alice_channel.external_state.netting_channel.address
    assert nettingaddress0 == nettingaddress1

    identifier = 1
    fee = 0
    transfermessage = alice_bob_channel.create_mediatedtransfer(
        alice_app.raiden.address,
        bob_app.raiden.address,
        fee,
        alice_to_bob_amount,
        identifier,
        expiration,
        hashlock,
    )
    alice_app.raiden.sign(transfermessage)
    alice_bob_channel.register_transfer(
        alice_app.raiden.get_block_number(),
        transfermessage,
    )
    bob_alice_channel.register_transfer(
        bob_app.raiden.get_block_number(),
        transfermessage,
    )

    assert_synched_channels(
        alice_bob_channel, alice_deposit, [],
        bob_alice_channel, bob_deposit, [transfermessage.lock],
    )

    # At this point we are assuming the following:
    #
    #    A -> B MediatedTransfer
    #    B -> A SecretRequest
    #    A -> B RevealSecret
    #    - protocol didn't continue
    #
    # B knowns the secret but doesn't have an updated balance proof, B needs to
    # call settle.

    # get proof, that locked transfermessage was in merkle tree, with locked.root
    lock = bob_alice_channel.partner_state.get_lock_by_hashlock(hashlock)
    assert sha3(secret) == hashlock
    unlock_proof = bob_alice_channel.partner_state.compute_proof_for_lock(secret, lock)

    root = merkleroot(bob_alice_channel.partner_state.merkletree)

    assert validate_proof(
        unlock_proof.merkle_proof,
        root,
        sha3(transfermessage.lock.as_bytes),
    )
    assert unlock_proof.lock_encoded == transfermessage.lock.as_bytes
    assert unlock_proof.secret == secret

    # a ChannelClose event will be generated, this will be polled by both apps
    # and each must start a task for calling settle
    balance_proof = transfermessage.to_balanceproof()
    bob_alice_channel.external_state.close(balance_proof)
    wait_until_block(alice_chain, alice_chain.block_number() + 1)

    assert alice_bob_channel.external_state.close_event.wait(timeout=15)
    assert bob_alice_channel.external_state.close_event.wait(timeout=15)

    assert alice_bob_channel.external_state.closed_block != 0
    assert bob_alice_channel.external_state.closed_block != 0
    assert alice_bob_channel.external_state.settled_block == 0
    assert bob_alice_channel.external_state.settled_block == 0

    # unlock will not be called by Channel.channel_closed because we did not
    # register the secret
    assert lock.expiration > alice_app.raiden.chain.block_number()
    assert lock.hashlock == sha3(secret)

    bob_alice_channel.external_state.netting_channel.withdraw([unlock_proof])

    settle_expiration = alice_chain.block_number() + settle_timeout + 2
    wait_until_block(alice_chain, settle_expiration)

    assert alice_bob_channel.external_state.settle_event.wait(timeout=15)
    assert bob_alice_channel.external_state.settle_event.wait(timeout=15)
    # settle must be called by the apps triggered by the ChannelClose event,
    # and the channels must update it's state based on the ChannelSettled event
    assert alice_bob_channel.external_state.settled_block != 0
    assert bob_alice_channel.external_state.settled_block != 0

    address0 = alice_app.raiden.address
    address1 = bob_app.raiden.address

    alice_netted_balance = alice_balance + alice_deposit - alice_to_bob_amount
    bob_netted_balance = bob_balance + bob_deposit + alice_to_bob_amount

    assert token.balance_of(address0) == alice_netted_balance
    assert token.balance_of(address1) == bob_netted_balance

    # Now let's query the WAL to see if the state changes were logged as expected
    state_changes = [
        change[1] for change in get_all_state_changes(alice_app.raiden.transaction_log)
        if not isinstance(change[1], Block)
    ]

    assert must_contain_entry(state_changes, ContractReceiveClosed, {
        'channel_address': nettingaddress0,
        'closing_address': bob_app.raiden.address,
        'block_number': alice_bob_channel.external_state.closed_block,
    })

    assert must_contain_entry(state_changes, ReceiveSecretReveal, {
        'secret': secret,
        'sender': bob_app.raiden.address,
    })

    assert must_contain_entry(state_changes, ContractReceiveWithdraw, {
        'channel_address': nettingaddress0,
        'secret': secret,
        'receiver': bob_app.raiden.address,
    })

    assert must_contain_entry(state_changes, ContractReceiveSettled, {
        'channel_address': nettingaddress0,
        'block_number': bob_alice_channel.external_state.settled_block,
    })
Exemple #39
0
def test_settlement(raiden_network, settle_timeout, reveal_timeout):
    alice_app, bob_app = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    setup_messages_cb()

    alice_graph = alice_app.raiden.channelgraphs.values()[0]
    bob_graph = bob_app.raiden.channelgraphs.values()[0]
    assert alice_graph.token_address == bob_graph.token_address

    alice_bob_channel = alice_graph.partneraddress_channel[
        bob_app.raiden.address]
    bob_alice_channel = bob_graph.partneraddress_channel[
        alice_app.raiden.address]

    alice_deposit = alice_bob_channel.balance
    bob_deposit = bob_alice_channel.balance

    token = alice_app.raiden.chain.token(alice_bob_channel.token_address)

    alice_balance = token.balance_of(alice_app.raiden.address)
    bob_balance = token.balance_of(bob_app.raiden.address)

    alice_chain = alice_app.raiden.chain

    alice_to_bob_amount = 10
    expiration = alice_app.raiden.chain.block_number() + reveal_timeout + 1
    secret = 'secretsecretsecretsecretsecretse'
    hashlock = sha3(secret)

    assert bob_app.raiden.address in alice_graph.partneraddress_channel

    nettingaddress0 = alice_bob_channel.external_state.netting_channel.address
    nettingaddress1 = bob_alice_channel.external_state.netting_channel.address
    assert nettingaddress0 == nettingaddress1

    identifier = 1
    fee = 0
    transfermessage = alice_bob_channel.create_mediatedtransfer(
        alice_app.raiden.get_block_number(),
        alice_app.raiden.address,
        bob_app.raiden.address,
        fee,
        alice_to_bob_amount,
        identifier,
        expiration,
        hashlock,
    )
    alice_app.raiden.sign(transfermessage)
    alice_bob_channel.register_transfer(
        alice_app.raiden.get_block_number(),
        transfermessage,
    )
    bob_alice_channel.register_transfer(
        bob_app.raiden.get_block_number(),
        transfermessage,
    )

    assert_synched_channels(
        alice_bob_channel,
        alice_deposit,
        [],
        bob_alice_channel,
        bob_deposit,
        [transfermessage.lock],
    )

    # At this point we are assuming the following:
    #
    #    A -> B MediatedTransfer
    #    B -> A SecretRequest
    #    A -> B RevealSecret
    #    - protocol didn't continue
    #
    # B knowns the secret but doesn't have an updated balance proof, B needs to
    # call settle.

    # get proof, that locked transfermessage was in merkle tree, with locked.root
    lock = bob_alice_channel.our_state.balance_proof.get_lock_by_hashlock(
        hashlock)
    assert sha3(secret) == hashlock
    unlock_proof = bob_alice_channel.our_state.balance_proof.compute_proof_for_lock(
        secret, lock)

    root = bob_alice_channel.our_state.balance_proof.merkleroot_for_unclaimed()

    assert check_proof(
        unlock_proof.merkle_proof,
        root,
        sha3(transfermessage.lock.as_bytes),
    )
    assert unlock_proof.lock_encoded == transfermessage.lock.as_bytes
    assert unlock_proof.secret == secret

    # a ChannelClose event will be generated, this will be polled by both apps
    # and each must start a task for calling settle
    bob_alice_channel.external_state.netting_channel.close(transfermessage)
    wait_until_block(alice_chain, alice_chain.block_number() + 1)

    assert alice_bob_channel.external_state.close_event.wait(timeout=15)
    assert bob_alice_channel.external_state.close_event.wait(timeout=15)

    assert alice_bob_channel.external_state.closed_block != 0
    assert bob_alice_channel.external_state.closed_block != 0
    assert alice_bob_channel.external_state.settled_block == 0
    assert bob_alice_channel.external_state.settled_block == 0

    # unlock will not be called by Channel.channel_closed because we did not
    # register the secret
    assert lock.expiration > alice_app.raiden.chain.block_number()
    assert lock.hashlock == sha3(secret)

    bob_alice_channel.external_state.netting_channel.withdraw([unlock_proof])

    settle_expiration = alice_chain.block_number() + settle_timeout + 2
    wait_until_block(alice_chain, settle_expiration)

    assert alice_bob_channel.external_state.settle_event.wait(timeout=15)
    assert bob_alice_channel.external_state.settle_event.wait(timeout=15)
    # settle must be called by the apps triggered by the ChannelClose event,
    # and the channels must update it's state based on the ChannelSettled event
    assert alice_bob_channel.external_state.settled_block != 0
    assert bob_alice_channel.external_state.settled_block != 0

    address0 = alice_app.raiden.address
    address1 = bob_app.raiden.address

    alice_netted_balance = alice_balance + alice_deposit - alice_to_bob_amount
    bob_netted_balance = bob_balance + bob_deposit + alice_to_bob_amount

    assert token.balance_of(address0) == alice_netted_balance
    assert token.balance_of(address1) == bob_netted_balance

    # Now let's query the WAL to see if the state changes were logged as expected
    state_changes = [
        change[1]
        for change in get_all_state_changes(alice_app.raiden.transaction_log)
        if not isinstance(change[1], Block)
    ]

    state_change1 = state_changes[0]
    state_change2 = state_changes[1]
    state_change3 = state_changes[2]
    state_change4 = state_changes[3]

    assert isinstance(state_change1, ContractReceiveClosed)
    assert state_change1.channel_address == nettingaddress0
    assert state_change1.closing_address == bob_app.raiden.address
    assert state_change1.block_number == alice_bob_channel.external_state.closed_block

    # Can't be sure of the order in which we encounter the SecretReveal and the withdraw
    assert_secretreveal_or_withdraw(state_change2, secret, nettingaddress0,
                                    bob_app.raiden.address)
    assert_secretreveal_or_withdraw(state_change3, secret, nettingaddress0,
                                    bob_app.raiden.address)

    assert isinstance(state_change4, ContractReceiveSettled)
    assert state_change4.channel_address == nettingaddress0
    assert state_change4.block_number == bob_alice_channel.external_state.settled_block
def test_automatic_dispute(raiden_network, deposit, settle_timeout):
    app0, app1 = raiden_network
    channel0 = list(list(app0.raiden.token_to_channelgraph.values())[0].partneraddress_to_channel.values())[0]  # noqa: E501
    channel1 = list(list(app1.raiden.token_to_channelgraph.values())[0].partneraddress_to_channel.values())[0]  # noqa: E501
    privatekey0 = app0.raiden.private_key
    privatekey1 = app1.raiden.private_key
    address0 = privatekey_to_address(privatekey0.secret)
    address1 = privatekey_to_address(privatekey1.secret)
    token = app0.raiden.chain.token(channel0.token_address)
    initial_balance0 = token.balance_of(address0)
    initial_balance1 = token.balance_of(address1)

    # Alice sends Bob 10 tokens
    amount_alice1 = 10
    identifier_alice1 = 1
    alice_first_transfer = channel0.create_directtransfer(
        amount_alice1,
        identifier_alice1,
    )
    alice_first_transfer.sign(privatekey0, address0)
    channel0.register_transfer(
        app0.raiden.get_block_number(),
        alice_first_transfer,
    )
    channel1.register_transfer(
        app1.raiden.get_block_number(),
        alice_first_transfer,
    )

    # Bob sends Alice 50 tokens
    amount_bob1 = 50
    identifier_bob1 = 1
    bob_first_transfer = channel1.create_directtransfer(
        amount_bob1,
        identifier_bob1,
    )
    bob_first_transfer.sign(privatekey1, address1)
    channel0.register_transfer(
        app0.raiden.get_block_number(),
        bob_first_transfer,
    )
    channel1.register_transfer(
        app1.raiden.get_block_number(),
        bob_first_transfer,
    )

    # Finally Alice sends Bob 60 tokens
    identifier_alice2 = 2
    amount_alice2 = 60
    alice_second_transfer = channel0.create_directtransfer(
        amount_alice2,
        identifier_alice2,
    )
    alice_second_transfer.sign(privatekey0, address0)
    channel0.register_transfer(
        app0.raiden.get_block_number(),
        alice_second_transfer,
    )
    channel1.register_transfer(
        app1.raiden.get_block_number(),
        alice_second_transfer,
    )

    # Alice can only provide one of Bob's transfer, so she is incentivized to
    # use the one with the largest transferred_amount.
    channel0.external_state.close(channel0.partner_state.balance_proof)
    chain0 = app0.raiden.chain
    wait_until_block(chain0, chain0.block_number() + 1)

    assert channel0.external_state.close_event.wait(timeout=25)
    assert channel1.external_state.close_event.wait(timeout=25)

    assert channel0.external_state.closed_block != 0
    assert channel1.external_state.closed_block != 0

    # Bob needs to provide a transfer otherwise it's netted balance will be
    # wrong, so he is incetivized to use Alice's transfer with the largest
    # transferred_amount.
    #
    # This is done automatically
    # channel1.external_state.update_transfer(
    #     alice_second_transfer,
    # )

    # wait until the settle timeout has passed
    settle_expiration = chain0.block_number() + settle_timeout
    wait_until_block(chain0, settle_expiration)

    # the settle event must be set
    assert channel0.external_state.settle_event.wait(timeout=60)
    assert channel1.external_state.settle_event.wait(timeout=60)

    # check that the channel is properly settled and that Bob's client
    # automatically called updateTransfer() to reflect the actual transactions
    assert channel0.external_state.settled_block != 0
    assert channel1.external_state.settled_block != 0
    assert token.balance_of(channel0.external_state.netting_channel.address) == 0
    total_alice = amount_alice1 + amount_alice2
    total_bob = amount_bob1
    assert token.balance_of(address0) == initial_balance0 + deposit - total_alice + total_bob
    assert token.balance_of(address1) == initial_balance1 + deposit + total_alice - total_bob
def test_settled_lock(assets_addresses, raiden_network, settle_timeout, reveal_timeout):
    """ Any transfer following a secret revealed must update the locksroot, so
    that an attacker cannot reuse a secret to double claim a lock.
    """
    asset = assets_addresses[0]
    amount = 30

    app0, app1, app2, _ = raiden_network  # pylint: disable=unbalanced-tuple-unpacking
    address0 = app0.raiden.address
    address1 = app1.raiden.address

    # mediated transfer
    identifier = 1
    expiration = app0.raiden.chain.block_number() + settle_timeout - reveal_timeout
    secret = pending_mediated_transfer(
        raiden_network,
        asset,
        amount,
        identifier,
        expiration,
    )
    hashlock = sha3(secret)

    # get a proof for the pending transfer
    back_channel = channel(app1, app0, asset)
    secret_transfer = get_received_transfer(back_channel, 0)
    lock = back_channel.our_state.balance_proof.get_lock_by_hashlock(hashlock)
    unlock_proof = back_channel.our_state.balance_proof.compute_proof_for_lock(secret, lock)

    # reveal the secret
    claim_lock(raiden_network, asset, secret)

    # a new transfer to update the hashlock
    direct_transfer(app0, app1, asset, amount)

    forward_channel = channel(app0, app1, asset)
    last_transfer = get_sent_transfer(forward_channel, 1)

    # call close giving the secret for a transfer that has being revealed
    back_channel.external_state.netting_channel.close(
        app1.raiden.address,
        last_transfer,
        None
    )

    # check that the double unlock will failed
    with pytest.raises(Exception):
        back_channel.external_state.netting_channel.unlock(
            app1.raiden.address,
            [(unlock_proof, secret_transfer.lock.as_bytes, secret)],
        )

    # forward the block number to allow settle
    settle_expiration = app2.raiden.chain.block_number() + settle_timeout
    wait_until_block(app2.raiden.chain, settle_expiration)

    back_channel.external_state.netting_channel.settle()

    participant0 = back_channel.external_state.netting_channel.contract.participants[address0]
    participant1 = back_channel.external_state.netting_channel.contract.participants[address1]

    assert participant0.netted == participant0.deposit - amount * 2
    assert participant1.netted == participant1.deposit + amount * 2
Exemple #42
0
def test_settlement(raiden_network, settle_timeout):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    setup_messages_cb()

    asset_manager0 = app0.raiden.managers_by_asset_address.values()[0]
    asset_manager1 = app1.raiden.managers_by_asset_address.values()[0]

    chain0 = app0.raiden.chain

    channel0 = asset_manager0.partneraddress_channel[app1.raiden.address]
    channel1 = asset_manager1.partneraddress_channel[app0.raiden.address]

    balance0 = channel0.balance
    balance1 = channel1.balance

    amount = 10
    expiration = app0.raiden.chain.block_number() + 5
    secret = 'secret'
    hashlock = sha3(secret)

    assert app1.raiden.address in asset_manager0.partneraddress_channel
    assert asset_manager0.asset_address == asset_manager1.asset_address
    assert channel0.external_state.netting_channel.address == channel1.external_state.netting_channel.address

    transfermessage = channel0.create_lockedtransfer(amount, expiration,
                                                     hashlock)
    app0.raiden.sign(transfermessage)
    channel0.register_transfer(transfermessage)
    channel1.register_transfer(transfermessage)

    assert_synched_channels(
        channel0,
        balance0,
        [],
        channel1,
        balance1,
        [transfermessage.lock],
    )

    # Bob learns the secret, but Alice did not send a signed updated balance to
    # reflect this Bob wants to settle

    # get proof, that locked transfermessage was in merkle tree, with locked.root
    lock = channel1.our_state.balance_proof.get_lock_by_hashlock(hashlock)
    unlock_proof = channel1.our_state.balance_proof.compute_proof_for_lock(
        secret, lock)

    root = channel1.our_state.balance_proof.merkleroot_for_unclaimed()

    assert check_proof(
        unlock_proof.merkle_proof,
        root,
        sha3(transfermessage.lock.as_bytes),
    )
    assert unlock_proof.lock_encoded == transfermessage.lock.as_bytes
    assert unlock_proof.secret == secret

    channel0.external_state.netting_channel.close(
        app0.raiden.address,
        transfermessage,
        None,
    )

    channel0.external_state.netting_channel.unlock(
        app0.raiden.address,
        [unlock_proof],
    )

    settle_expiration = chain0.block_number() + settle_timeout
    wait_until_block(chain0, settle_expiration)

    channel0.external_state.netting_channel.settle()
def test_settlement(raiden_network, settle_timeout, reveal_timeout):
    app0, app1 = raiden_network  # pylint: disable=unbalanced-tuple-unpacking

    setup_messages_cb()

    asset_manager0 = app0.raiden.managers_by_asset_address.values()[0]
    asset_manager1 = app1.raiden.managers_by_asset_address.values()[0]

    chain0 = app0.raiden.chain

    channel0 = asset_manager0.partneraddress_channel[app1.raiden.address]
    channel1 = asset_manager1.partneraddress_channel[app0.raiden.address]

    balance0 = channel0.balance
    balance1 = channel1.balance

    amount = 10
    expiration = app0.raiden.chain.block_number() + reveal_timeout + 1
    secret = 'secret'
    hashlock = sha3(secret)

    assert app1.raiden.address in asset_manager0.partneraddress_channel
    assert asset_manager0.asset_address == asset_manager1.asset_address

    nettingaddress0 = channel0.external_state.netting_channel.address
    nettingaddress1 = channel1.external_state.netting_channel.address
    assert nettingaddress0 == nettingaddress1

    identifier = 1
    fee = 0
    transfermessage = channel0.create_mediatedtransfer(
        app0.raiden.address,
        app1.raiden.address,
        fee,
        amount,
        identifier,
        expiration,
        hashlock,
    )
    app0.raiden.sign(transfermessage)
    channel0.register_transfer(transfermessage)
    channel1.register_transfer(transfermessage)

    assert_synched_channels(
        channel0, balance0, [],
        channel1, balance1, [transfermessage.lock],
    )

    # At this point we are assuming the following:
    #
    #    A -> B MediatedTransfer
    #    B -> A SecretRequest
    #    A -> B RevealSecret
    #    - protocol didn't continue
    #
    # B knowns the secret but doesn't have an updated balance proof, B needs to
    # call settle.

    # get proof, that locked transfermessage was in merkle tree, with locked.root
    lock = channel1.our_state.balance_proof.get_lock_by_hashlock(hashlock)
    unlock_proof = channel1.our_state.balance_proof.compute_proof_for_lock(secret, lock)

    root = channel1.our_state.balance_proof.merkleroot_for_unclaimed()

    assert check_proof(
        unlock_proof.merkle_proof,
        root,
        sha3(transfermessage.lock.as_bytes),
    )
    assert unlock_proof.lock_encoded == transfermessage.lock.as_bytes
    assert unlock_proof.secret == secret

    # a ChannelClose event will be generated, this will be polled by both apps
    # and each must start a task for calling settle
    channel0.external_state.netting_channel.close(
        app0.raiden.address,
        transfermessage,
        None,
    )

    # unlock will not be called by Channel.channel_closed because we did not
    # register the secret
    channel0.external_state.netting_channel.unlock(
        app0.raiden.address,
        [unlock_proof],
    )

    settle_expiration = chain0.block_number() + settle_timeout
    wait_until_block(chain0, settle_expiration)

    # settle must be called by the apps triggered by the ChannelClose event,
    # and the channels must update it's state based on the ChannelSettled event
    assert channel0.external_state.settled_block != 0
    assert channel1.external_state.settled_block != 0
def test_query_events(raiden_chain, deposit, settle_timeout, events_poll_timeout):
    app0, app1 = raiden_chain  # pylint: disable=unbalanced-tuple-unpacking

    token_address = app0.raiden.default_registry.token_addresses()[0]

    assert len(app0.raiden.token_to_channelgraph[token_address].address_to_channel) == 0
    assert len(app1.raiden.token_to_channelgraph[token_address].address_to_channel) == 0

    token0 = app0.raiden.chain.token(token_address)
    manager0 = app0.raiden.default_registry.manager_by_token(token_address)

    events = get_all_registry_events(
        app0.raiden.chain,
        app0.raiden.default_registry.address,
        events=ALL_EVENTS,
        from_block=0,
        to_block='latest',
    )

    assert len(events) == 1
    assert event_dicts_are_equal(events[0], {
        '_event_type': b'TokenAdded',
        'channel_manager_address': address_encoder(manager0.address),
        'token_address': address_encoder(token_address),
        'block_number': 'ignore',
    })

    events = get_all_registry_events(
        app0.raiden.chain,
        app0.raiden.default_registry.address,
        events=ALL_EVENTS,
        from_block=999999998,
        to_block=999999999,
    )
    assert not events

    netcontract_address = manager0.new_netting_channel(
        app1.raiden.address,
        settle_timeout,
    )

    events = get_all_channel_manager_events(
        app0.raiden.chain,
        manager0.address,
        events=ALL_EVENTS,
        from_block=0,
        to_block='latest',
    )

    assert len(events) == 1
    assert event_dicts_are_equal(events[0], {
        '_event_type': b'ChannelNew',
        'settle_timeout': settle_timeout,
        'netting_channel': address_encoder(netcontract_address),
        'participant1': address_encoder(app0.raiden.address),
        'participant2': address_encoder(app1.raiden.address),
        'block_number': 'ignore',
    })

    events = get_all_channel_manager_events(
        app0.raiden.chain,
        manager0.address,
        events=ALL_EVENTS,
        from_block=999999998,
        to_block=999999999,
    )
    assert not events

    netting_channel0 = app0.raiden.chain.netting_channel(netcontract_address)

    gevent.sleep(events_poll_timeout * 2)

    # channel is created but not opened and without funds
    assert len(app0.raiden.token_to_channelgraph[token_address].address_to_channel) == 1
    assert len(app1.raiden.token_to_channelgraph[token_address].address_to_channel) == 1

    channel0 = list(app0.raiden.token_to_channelgraph[token_address].address_to_channel.values())[0]  # noqa: E501
    channel1 = list(app1.raiden.token_to_channelgraph[token_address].address_to_channel.values())[0]  # noqa: E501

    assert_synched_channels(
        channel0, 0, [],
        channel1, 0, [],
    )

    token0.approve(netcontract_address, deposit)
    netting_channel0.deposit(deposit)

    all_netting_channel_events = get_all_netting_channel_events(
        app0.raiden.chain,
        netting_channel_address=netcontract_address,
        from_block=0,
        to_block='latest',
    )

    events = get_all_netting_channel_events(
        app0.raiden.chain,
        netcontract_address,
        events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_NEW_BALANCE)],
    )

    assert len(all_netting_channel_events) == 1
    assert len(events) == 1

    new_balance_event = {
        '_event_type': b'ChannelNewBalance',
        'token_address': address_encoder(token_address),
        'participant': address_encoder(app0.raiden.address),
        'balance': deposit,
        'block_number': 'ignore',
    }

    assert event_dicts_are_equal(all_netting_channel_events[-1], new_balance_event)
    assert event_dicts_are_equal(events[0], new_balance_event)

    channel0.external_state.close(None)

    all_netting_channel_events = get_all_netting_channel_events(
        app0.raiden.chain,
        netting_channel_address=netcontract_address,
        from_block=0,
        to_block='latest',
    )

    events = get_all_netting_channel_events(
        app0.raiden.chain,
        netcontract_address,
        events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_CLOSED)],
    )

    assert len(all_netting_channel_events) == 2
    assert len(events) == 1

    closed_event = {
        '_event_type': b'ChannelClosed',
        'closing_address': address_encoder(app0.raiden.address),
        'block_number': 'ignore',
    }

    assert event_dicts_are_equal(all_netting_channel_events[-1], closed_event)
    assert event_dicts_are_equal(events[0], closed_event)

    settle_expiration = app0.raiden.chain.block_number() + settle_timeout + 1
    wait_until_block(app0.raiden.chain, settle_expiration)

    channel1.external_state.settle()

    all_netting_channel_events = get_all_netting_channel_events(
        app0.raiden.chain,
        netting_channel_address=netcontract_address,
        from_block=0,
        to_block='latest',
    )

    events = get_all_netting_channel_events(
        app0.raiden.chain,
        netcontract_address,
        events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_SETTLED)],
    )

    assert len(all_netting_channel_events) == 3
    assert len(events) == 1

    settled_event = {
        '_event_type': b'ChannelSettled',
        'block_number': 'ignore',
    }

    assert event_dicts_are_equal(all_netting_channel_events[-1], settled_event)
    assert event_dicts_are_equal(events[0], settled_event)