예제 #1
0
def test_settle_is_automatically_called(raiden_network, token_addresses, deposit):
    """Settle is automatically called by one of the nodes."""
    app0, app1 = raiden_network
    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,
    )

    channel_identifier = get_channelstate(app0, app1, token_network_identifier).identifier

    # A ChannelClose event will be generated, this will be polled by both apps
    # and each must start a task for calling settle
    RaidenAPI(app1.raiden).channel_close(
        registry_address,
        token_address,
        app0.raiden.address,
    )

    waiting.wait_for_settle(
        app0.raiden,
        registry_address,
        token_address,
        [channel_identifier],
        app0.raiden.alarm.sleep_time,
    )

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

    state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )

    channel_state = get_channelstate(app0, app1, token_network_identifier)
    assert channel_state.close_transaction.finished_block_number
    assert channel_state.settle_transaction.finished_block_number

    assert must_contain_entry(state_changes, ContractReceiveChannelClosed, {
        'token_network_identifier': token_network_identifier,
        'channel_identifier': channel_identifier,
        'closing_address': app1.raiden.address,
        'closed_block_number': channel_state.close_transaction.finished_block_number,
    })

    assert must_contain_entry(state_changes, ContractReceiveChannelSettled, {
        'token_network_identifier': token_network_identifier,
        'channel_identifier': channel_identifier,
        'settle_block_number': channel_state.settle_transaction.finished_block_number,
    })
예제 #2
0
def test_close_channel_lack_of_balance_proof(raiden_chain, deposit, token_addresses):
    app0, app1 = raiden_chain
    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,
    )

    token_proxy = app0.raiden.chain.token(token_address)
    initial_balance0 = token_proxy.balance_of(app0.raiden.address)
    initial_balance1 = token_proxy.balance_of(app1.raiden.address)

    amount = 100
    identifier = 1
    secret = pending_mediated_transfer(
        raiden_chain,
        token_network_identifier,
        amount,
        identifier,
    )

    # Stop app0 to avoid sending the unlock
    app0.raiden.transport.stop_and_wait()

    reveal_secret = RevealSecret(
        random.randint(0, UINT64_MAX),
        secret,
    )
    app0.raiden.sign(reveal_secret)
    message_handler.on_message(app1.raiden, reveal_secret)

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

    channel_state = get_channelstate(app0, app1, token_network_identifier)
    waiting.wait_for_settle(
        app0.raiden,
        app0.raiden.default_registry.address,
        token_address,
        [channel_state.identifier],
        app0.raiden.alarm.sleep_time,
    )

    # wait for the node to call batch unlock
    with gevent.Timeout(10):
        wait_for_batch_unlock(
            app0,
            token_network_identifier,
            channel_state.partner_state.address,
            channel_state.our_state.address,
        )

    expected_balance0 = initial_balance0 + deposit - amount
    expected_balance1 = initial_balance1 + deposit + amount
    assert token_proxy.balance_of(app0.raiden.address) == expected_balance0
    assert token_proxy.balance_of(app1.raiden.address) == expected_balance1
def test_receive_directtransfer_invalidnonce(raiden_network, deposit, token_addresses):

    app0, app1 = raiden_network
    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,
    )
    channel0 = get_channelstate(app0, app1, token_network_identifier)

    transferred_amount = 10
    same_payment_identifier = 1
    message_identifier = random.randint(0, UINT64_MAX)

    event = channel.send_directtransfer(
        channel0,
        transferred_amount,
        message_identifier,
        same_payment_identifier,
    )

    direct_transfer_message = DirectTransfer.from_event(event)
    sign_and_inject(
        direct_transfer_message,
        app0.raiden.private_key,
        app0.raiden.address,
        app1,
    )

    # Send a *different* direct transfer with the *same nonce*
    invalid_transferred_amount = transferred_amount // 2
    message_identifier = random.randint(0, UINT64_MAX)

    invalid_direct_transfer_message = DirectTransfer(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=message_identifier,
        payment_identifier=same_payment_identifier,
        nonce=1,
        token_network_address=token_network_identifier,
        token=token_address,
        channel_identifier=channel0.identifier,
        transferred_amount=invalid_transferred_amount,
        locked_amount=0,
        recipient=app1.raiden.address,
        locksroot=EMPTY_MERKLE_ROOT,
    )

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

    assert_synched_channel_state(
        token_network_identifier,
        app0, deposit - transferred_amount, [],
        app1, deposit + transferred_amount, [],
    )
예제 #4
0
def test_deposit_updates_balance_immediately(raiden_chain, token_addresses):
    """ Test that the balance of a channel gets updated by the deposit() call
    immediately and without having to wait for the
    `ContractReceiveChannelNewBalance` message since the API needs to return
    the channel with the deposit balance updated.
    """
    app0, app1 = 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,
    )

    api0 = RaidenAPI(app0.raiden)

    old_state = get_channelstate(app0, app1, token_network_identifier)
    api0.set_total_channel_deposit(registry_address, token_address, app1.raiden.address, 210)
    new_state = get_channelstate(app0, app1, token_network_identifier)

    assert new_state.our_state.contract_balance == old_state.our_state.contract_balance + 10
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(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=message_identifier,
        payment_identifier=1,
        nonce=1,
        token_network_address=token_network_identifier,
        token=token_address,
        channel_identifier=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, [],
    )
def test_receive_lockedtransfer_invalidrecipient(
        raiden_network,
        token_addresses,
        reveal_timeout,
        deposit,
):

    app0, app1 = raiden_network
    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,
    )
    channel0 = get_channelstate(app0, app1, token_network_identifier)

    payment_identifier = 1
    invalid_recipient = make_address()
    lock_amount = 10
    expiration = reveal_timeout * 2
    mediated_transfer_message = LockedTransfer(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=random.randint(0, UINT64_MAX),
        payment_identifier=payment_identifier,
        nonce=1,
        token_network_address=token_network_identifier,
        token=token_address,
        channel_identifier=channel0.identifier,
        transferred_amount=0,
        locked_amount=lock_amount,
        recipient=invalid_recipient,
        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,
    )

    assert_synced_channel_state(
        token_network_identifier,
        app0, deposit, [],
        app1, deposit, [],
    )
def test_receive_directtransfer_invalidlocksroot(raiden_network, token_addresses):
    app0, app1 = raiden_network
    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,
    )

    channel0 = get_channelstate(app0, app1, token_network_identifier)
    balance0 = channel.get_balance(channel0.our_state, channel0.partner_state)
    balance1 = channel.get_balance(channel0.partner_state, channel0.our_state)

    payment_identifier = 1
    invalid_locksroot = UNIT_SECRETHASH
    channel_identifier = channel0.identifier
    message_identifier = random.randint(0, UINT64_MAX)

    direct_transfer_message = DirectTransfer(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=message_identifier,
        payment_identifier=payment_identifier,
        nonce=1,
        token_network_address=token_network_identifier,
        token=token_address,
        channel_identifier=channel_identifier,
        transferred_amount=0,
        locked_amount=0,
        recipient=app1.raiden.address,
        locksroot=invalid_locksroot,
    )

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

    assert_synched_channel_state(
        token_network_identifier,
        app0, balance0, [],
        app1, balance1, [],
    )
def test_receive_directtransfer_invalidtoken(raiden_network, deposit, token_addresses):

    app0, app1 = raiden_network
    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,
    )

    channel0 = get_channelstate(app0, app1, token_network_identifier)
    message_identifier = random.randint(0, UINT64_MAX)

    payment_identifier = 1
    invalid_token_address = make_address()
    channel_identifier = channel0.identifier
    direct_transfer_message = DirectTransfer(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=message_identifier,
        payment_identifier=payment_identifier,
        nonce=1,
        token_network_address=token_network_identifier,
        token=invalid_token_address,
        channel_identifier=channel_identifier,
        transferred_amount=0,
        locked_amount=0,
        recipient=app1.raiden.address,
        locksroot=EMPTY_MERKLE_ROOT,
    )

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

    assert_synched_channel_state(
        token_network_identifier,
        app0, deposit, [],
        app1, deposit, [],
    )
예제 #9
0
def test_channel_deposit(raiden_chain, deposit, retry_timeout,
                         token_addresses):
    app0, app1 = raiden_chain
    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),
        app0.raiden.default_registry.address,
        token_address,
    )

    channel0 = get_channelstate(app0, app1, token_network_identifier)
    channel1 = get_channelstate(app1, app0, token_network_identifier)
    assert channel0 is None
    assert channel1 is None

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

    wait_both_channel_open(app0, app1, registry_address, token_address,
                           retry_timeout)

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

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

    wait_both_channel_deposit(
        app0,
        app1,
        registry_address,
        token_address,
        deposit,
        retry_timeout,
    )

    assert_synced_channel_state(
        token_network_identifier,
        app0,
        deposit,
        [],
        app1,
        0,
        [],
    )

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

    wait_both_channel_deposit(
        app1,
        app0,
        registry_address,
        token_address,
        deposit,
        retry_timeout,
    )

    assert_synced_channel_state(
        token_network_identifier,
        app0,
        deposit,
        [],
        app1,
        deposit,
        [],
    )
예제 #10
0
def run_test_settled_lock(
    token_addresses,
    raiden_network,
    deposit,
):
    """ Any transfer following a secret reveal must update the locksroot, so
    that an attacker cannot reuse a secret to double claim a lock.
    """
    app0, app1 = raiden_network
    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]
    amount = 30
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_registry.address,
        token_address,
    )

    hold_event_handler = HoldOffChainSecretRequest()
    app1.raiden.raiden_event_handler = hold_event_handler

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

    deposit0 = deposit
    deposit1 = deposit

    token_proxy = app0.raiden.chain.token(token_address)
    initial_balance0 = token_proxy.balance_of(address0)
    initial_balance1 = token_proxy.balance_of(address1)
    identifier = 1
    target = app1.raiden.address
    secret = sha3(target)
    secrethash = sha3(secret)

    secret_available = hold_event_handler.hold_secretrequest_for(
        secrethash=secrethash)

    app0.raiden.start_mediated_transfer_with_secret(
        token_network_identifier=token_network_identifier,
        amount=amount,
        fee=0,
        target=target,
        identifier=identifier,
        secret=secret,
    )

    secret_available.wait()  # wait for the messages to be exchanged

    # Save the merkle tree leaves from the pending transfer, used to test the unlock
    channelstate_0_1 = get_channelstate(app0, app1, token_network_identifier)
    batch_unlock = channel.get_batch_unlock(channelstate_0_1.our_state)
    assert batch_unlock

    hold_event_handler.release_secretrequest_for(
        app1.raiden,
        secrethash,
    )

    transfer(
        initiator_app=app0,
        target_app=app1,
        token_address=token_address,
        amount=amount,
        identifier=2,
    )

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

    waiting.wait_for_settle(
        app1.raiden,
        app1.raiden.default_registry.address,
        token_address,
        [channelstate_0_1.identifier],
        app1.raiden.alarm.sleep_time,
    )

    netting_channel = app1.raiden.chain.payment_channel(
        canonical_identifier=channelstate_0_1.canonical_identifier, )

    # The transfer locksroot must not contain the unlocked lock, the
    # unlock must fail.
    with pytest.raises(RaidenUnrecoverableError):
        netting_channel.unlock(
            merkle_tree_leaves=batch_unlock,
            participant=channelstate_0_1.our_state.address,
            partner=channelstate_0_1.partner_state.address,
        )

    expected_balance0 = initial_balance0 + deposit0 - amount * 2
    expected_balance1 = initial_balance1 + deposit1 + amount * 2

    assert token_proxy.balance_of(address0) == expected_balance0
    assert token_proxy.balance_of(address1) == expected_balance1
예제 #11
0
def run_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,
    )

    hold_event_handler = HoldOffChainSecretRequest()
    app2.raiden.raiden_event_handler = hold_event_handler

    # the attacker owns app0 and app2 and creates a transfer through app1
    identifier = 1
    target = app2.raiden.address
    secret = sha3(target)
    secrethash = sha3(secret)

    hold_event_handler.hold_secretrequest_for(secrethash=secrethash)

    app0.raiden.start_mediated_transfer_with_secret(
        token_network_identifier=token_network_identifier,
        amount=amount,
        fee=0,
        target=target,
        identifier=identifier,
        secret=secret,
    )

    gevent.sleep(1)  # wait for the messages to be exchanged

    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
    app2.raiden.chain.wait_until_block(
        target_block_number=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
예제 #12
0
def test_raidenapi_channel_lifecycle(raiden_network, token_addresses, deposit,
                                     retry_timeout, settle_timeout_max):
    """Uses RaidenAPI to go through a complete channel lifecycle."""
    node1, node2 = raiden_network
    token_address = token_addresses[0]
    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_app(node1), node1.raiden.default_registry.address,
        token_address)
    assert token_network_address

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

    registry_address = node1.raiden.default_registry.address

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

    # Make sure invalid arguments to get_channel_list are caught
    with pytest.raises(UnknownTokenAddress):
        api1.get_channel_list(registry_address=registry_address,
                              token_address=None,
                              partner_address=api2.address)

    address_for_lowest_settle_timeout = make_address()
    lowest_valid_settle_timeout = node1.raiden.config.reveal_timeout * 2

    # Make sure a small settle timeout is not accepted when opening a channel
    with pytest.raises(InvalidSettleTimeout):
        api1.channel_open(
            registry_address=node1.raiden.default_registry.address,
            token_address=token_address,
            partner_address=address_for_lowest_settle_timeout,
            settle_timeout=lowest_valid_settle_timeout - 1,
        )

    # Make sure the smallest settle timeout is accepted
    api1.channel_open(
        registry_address=node1.raiden.default_registry.address,
        token_address=token_address,
        partner_address=address_for_lowest_settle_timeout,
        settle_timeout=lowest_valid_settle_timeout,
    )

    address_for_highest_settle_timeout = make_address()
    highest_valid_settle_timeout = settle_timeout_max

    # Make sure a large settle timeout is not accepted when opening a channel
    with pytest.raises(InvalidSettleTimeout):
        api1.channel_open(
            registry_address=node1.raiden.default_registry.address,
            token_address=token_address,
            partner_address=address_for_highest_settle_timeout,
            settle_timeout=highest_valid_settle_timeout + 1,
        )

    # Make sure the highest settle timeout is accepted
    api1.channel_open(
        registry_address=node1.raiden.default_registry.address,
        token_address=token_address,
        partner_address=address_for_highest_settle_timeout,
        settle_timeout=highest_valid_settle_timeout,
    )

    # 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_address)
    assert channel.get_status(channel12) == ChannelState.STATE_OPENED

    registry_address = api1.raiden.default_registry.address
    # Check that giving a 0 total deposit is not accepted
    with pytest.raises(DepositMismatch):
        api1.set_total_channel_deposit(
            registry_address=registry_address,
            token_address=token_address,
            partner_address=api2.address,
            total_deposit=TokenAmount(0),
        )
    # Load the new state with the deposit
    api1.set_total_channel_deposit(
        registry_address=registry_address,
        token_address=token_address,
        partner_address=api2.address,
        total_deposit=deposit,
    )

    # let's make sure it's idempotent. Same deposit should raise deposit mismatch limit
    with pytest.raises(DepositMismatch):
        api1.set_total_channel_deposit(registry_address, token_address,
                                       api2.address, deposit)

    channel12 = get_channelstate(node1, node2, token_network_address)

    assert channel.get_status(channel12) == ChannelState.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) == NetworkState.REACHABLE
    assert api2.get_node_network_state(api1.address) == NetworkState.REACHABLE

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

    # Load the new state with the channel closed
    channel12 = get_channelstate(node1, node2, token_network_address)
    assert channel.get_status(channel12) == ChannelState.STATE_CLOSED

    with pytest.raises(UnexpectedChannelState):
        api1.set_total_channel_deposit(registry_address, token_address,
                                       api2.address, deposit + 100)

    assert wait_for_state_change(
        node1.raiden,
        ContractReceiveChannelSettled,
        {
            "canonical_identifier": {
                "token_network_address": token_network_address,
                "channel_identifier": channel12.identifier,
            }
        },
        retry_timeout,
    )
예제 #13
0
def run_test_lock_expiry(raiden_network, token_addresses, deposit):
    alice_app, bob_app = raiden_network
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(alice_app),
        alice_app.raiden.default_registry.address,
        token_address,
    )

    hold_event_handler = HoldOffChainSecretRequest()
    wait_message_handler = WaitForMessage()
    bob_app.raiden.message_handler = wait_message_handler
    bob_app.raiden.raiden_event_handler = hold_event_handler

    token_network = views.get_token_network_by_identifier(
        views.state_from_app(alice_app),
        token_network_identifier,
    )

    channel_state = get_channelstate(alice_app, bob_app,
                                     token_network_identifier)
    channel_identifier = channel_state.identifier

    assert channel_identifier in token_network.partneraddresses_to_channelidentifiers[
        bob_app.raiden.address]

    alice_to_bob_amount = 10
    identifier = 1
    target = bob_app.raiden.address
    transfer_1_secret = factories.make_secret(0)
    transfer_1_secrethash = sha3(transfer_1_secret)
    transfer_2_secret = factories.make_secret(1)
    transfer_2_secrethash = sha3(transfer_2_secret)

    hold_event_handler.hold_secretrequest_for(secrethash=transfer_1_secrethash)
    transfer1_received = wait_message_handler.wait_for_message(
        LockedTransfer,
        {'lock': {
            'secrethash': transfer_1_secrethash
        }},
    )
    transfer2_received = wait_message_handler.wait_for_message(
        LockedTransfer,
        {'lock': {
            'secrethash': transfer_2_secrethash
        }},
    )
    remove_expired_lock_received = wait_message_handler.wait_for_message(
        LockExpired,
        {'secrethash': transfer_1_secrethash},
    )

    alice_app.raiden.start_mediated_transfer_with_secret(
        token_network_identifier=token_network_identifier,
        amount=alice_to_bob_amount,
        fee=0,
        target=target,
        identifier=identifier,
        secret=transfer_1_secret,
    )
    transfer1_received.wait()

    alice_bob_channel_state = get_channelstate(alice_app, bob_app,
                                               token_network_identifier)
    lock = channel.get_lock(alice_bob_channel_state.our_state,
                            transfer_1_secrethash)

    # This is the current state of the protocol:
    #
    #    A -> B LockedTransfer
    #    B -> A SecretRequest
    #    - protocol didn't continue
    assert_synced_channel_state(
        token_network_identifier,
        alice_app,
        deposit,
        [lock],
        bob_app,
        deposit,
        [],
    )

    # Verify lock is registered in both channel states
    alice_channel_state = get_channelstate(alice_app, bob_app,
                                           token_network_identifier)
    assert transfer_1_secrethash in alice_channel_state.our_state.secrethashes_to_lockedlocks

    bob_channel_state = get_channelstate(bob_app, alice_app,
                                         token_network_identifier)
    assert transfer_1_secrethash in bob_channel_state.partner_state.secrethashes_to_lockedlocks

    alice_chain_state = views.state_from_raiden(alice_app.raiden)
    assert transfer_1_secrethash in alice_chain_state.payment_mapping.secrethashes_to_task

    remove_expired_lock_received.wait()

    alice_channel_state = get_channelstate(alice_app, bob_app,
                                           token_network_identifier)
    assert transfer_1_secrethash not in alice_channel_state.our_state.secrethashes_to_lockedlocks

    # Verify Bob received the message and processed the LockExpired message
    bob_channel_state = get_channelstate(bob_app, alice_app,
                                         token_network_identifier)
    assert transfer_1_secrethash not in bob_channel_state.partner_state.secrethashes_to_lockedlocks

    alice_chain_state = views.state_from_raiden(alice_app.raiden)
    assert transfer_1_secrethash not in alice_chain_state.payment_mapping.secrethashes_to_task

    # Make another transfer
    alice_to_bob_amount = 10
    identifier = 2

    hold_event_handler.hold_secretrequest_for(secrethash=transfer_2_secrethash)

    alice_app.raiden.start_mediated_transfer_with_secret(
        token_network_identifier=token_network_identifier,
        amount=alice_to_bob_amount,
        fee=0,
        target=target,
        identifier=identifier,
        secret=transfer_2_secret,
    )
    transfer2_received.wait()

    # Make sure the other transfer still exists
    alice_chain_state = views.state_from_raiden(alice_app.raiden)
    assert transfer_2_secrethash in alice_chain_state.payment_mapping.secrethashes_to_task

    bob_channel_state = get_channelstate(bob_app, alice_app,
                                         token_network_identifier)
    assert transfer_2_secrethash in bob_channel_state.partner_state.secrethashes_to_lockedlocks
예제 #14
0
def test_settled_lock(token_addresses, raiden_network, deposit):
    """ Any transfer following a secret reveal must update the locksroot, so
    that an attacker cannot reuse a secret to double claim a lock.
    """
    app0, app1 = raiden_network
    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]
    amount = 30
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_registry.address,
        token_address,
    )

    hold_event_handler = HoldOffChainSecretRequest()
    app1.raiden.raiden_event_handler = hold_event_handler

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

    deposit0 = deposit
    deposit1 = deposit

    token_proxy = app0.raiden.chain.token(token_address)
    initial_balance0 = token_proxy.balance_of(address0)
    initial_balance1 = token_proxy.balance_of(address1)
    identifier = 1
    target = app1.raiden.address
    secret = sha3(target)
    secrethash = sha3(secret)

    secret_available = hold_event_handler.hold_secretrequest_for(secrethash=secrethash)

    app0.raiden.start_mediated_transfer_with_secret(
        token_network_identifier,
        amount,
        target,
        identifier,
        secret,
    )

    secret_available.wait()  # wait for the messages to be exchanged

    # Save the merkle tree leaves from the pending transfer, used to test the unlock
    channelstate_0_1 = get_channelstate(app0, app1, token_network_identifier)
    batch_unlock = channel.get_batch_unlock(channelstate_0_1.our_state)
    assert batch_unlock

    hold_event_handler.release_secretrequest_for(
        app1.raiden,
        secrethash,
    )

    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=amount,
        identifier=2,
    )

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

    waiting.wait_for_settle(
        app1.raiden,
        app1.raiden.default_registry.address,
        token_address,
        [channelstate_0_1.identifier],
        app1.raiden.alarm.sleep_time,
    )

    netting_channel = app1.raiden.chain.payment_channel(
        token_network_identifier,
        channelstate_0_1.identifier,
    )

    # The transfer locksroot must not contain the unlocked lock, the
    # unlock must fail.
    with pytest.raises(Exception):
        netting_channel.unlock(
            channelstate_0_1.partner_state.address,
            batch_unlock,
        )

    expected_balance0 = initial_balance0 + deposit0 - amount * 2
    expected_balance1 = initial_balance1 + deposit1 + amount * 2

    assert token_proxy.balance_of(address0) == expected_balance0
    assert token_proxy.balance_of(address1) == expected_balance1
예제 #15
0
def test_node_can_settle_if_close_didnt_use_any_balance_proof(
        raiden_network,
        number_of_nodes,
        deposit,
        token_addresses,
        network_wait,
):
    """ A node must be able to settle a channel, even if the partner used an
    old balance proof to close it.

    This test will:
    - Make a transfer from app0 to app1, to make sure there are balance
    proofs available
    - Call close manually in behalf of app1, without any balance proof data
    - Assert that app0 can settle the closed channel, even though app1 didn't
    use the latest balance proof
    """

    app0, app1 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    registry_address = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state=chain_state,
        payment_network_id=payment_network_id,
        token_address=token_address,
    )
    channel_identifier = get_channelstate(app0, app1, token_network_identifier).identifier

    # make a transfer from app0 to app1 so that app1 is supposed to have a non
    # empty balance hash
    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=1,
        timeout=network_wait * number_of_nodes,
    )
    # stop app1 - the test uses token_network_contract now
    app1.stop()
    token_network_contract = TokenNetwork(
        jsonrpc_client=app1.raiden.chain.client,
        token_network_address=token_network_identifier,
        contract_manager=app1.raiden.contract_manager,
    )

    # app1 closes the channel with an empty hash instead of the expected hash
    # of the transferred amount from app0
    token_network_contract.close(
        channel_identifier=channel_identifier,
        partner=app0.raiden.address,
        balance_hash=EMPTY_HASH,
        nonce=0,
        additional_hash=EMPTY_HASH,
        signature=EMPTY_SIGNATURE,
    )
    waiting.wait_for_close(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )
    waiting.wait_for_settle(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )
    state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )
    assert must_contain_entry(state_changes, ContractReceiveChannelSettled, {
        'token_network_identifier': token_network_identifier,
        'channel_identifier': channel_identifier,
    })
예제 #16
0
def run_test_batch_unlock_after_restart(raiden_network, token_addresses, deposit):
    """Simulate the case where:
    - A sends B a transfer
    - B sends A a transfer
    - Secrets were never revealed
    - B closes channel
    - A crashes
    - Wait for settle
    - Wait for unlock from B
    - Restart A
    At this point, the current unlock logic will try to unlock
    iff the node gains from unlocking. Which means that the node will try to unlock
    either side. In the above scenario, each node will unlock its side.
    This test makes sure that we do NOT invalidate A's unlock transaction based
    on the ContractReceiveChannelBatchUnlock caused by B's unlock.
    """
    alice_app, bob_app = raiden_network
    registry_address = alice_app.raiden.default_registry.address
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state=views.state_from_app(alice_app),
        payment_network_id=alice_app.raiden.default_registry.address,
        token_address=token_address,
    )
    timeout = 10

    token_network = views.get_token_network_by_identifier(
        chain_state=views.state_from_app(alice_app), token_network_id=token_network_identifier
    )

    channel_identifier = get_channelstate(alice_app, bob_app, token_network_identifier).identifier

    assert (
        channel_identifier
        in token_network.partneraddresses_to_channelidentifiers[bob_app.raiden.address]
    )

    alice_to_bob_amount = 10
    identifier = 1

    alice_transfer_secret = sha3(alice_app.raiden.address)
    alice_transfer_secrethash = sha3(alice_transfer_secret)

    bob_transfer_secret = sha3(bob_app.raiden.address)
    bob_transfer_secrethash = sha3(bob_transfer_secret)

    alice_transfer_hold = bob_app.raiden.raiden_event_handler.hold_secretrequest_for(
        secrethash=alice_transfer_secrethash
    )
    bob_transfer_hold = alice_app.raiden.raiden_event_handler.hold_secretrequest_for(
        secrethash=bob_transfer_secrethash
    )

    alice_app.raiden.start_mediated_transfer_with_secret(
        token_network_identifier=token_network_identifier,
        amount=alice_to_bob_amount,
        fee=0,
        target=bob_app.raiden.address,
        identifier=identifier,
        payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE,
        secret=alice_transfer_secret,
    )

    bob_app.raiden.start_mediated_transfer_with_secret(
        token_network_identifier=token_network_identifier,
        amount=alice_to_bob_amount,
        fee=0,
        target=alice_app.raiden.address,
        identifier=identifier + 1,
        payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE,
        secret=bob_transfer_secret,
    )

    alice_transfer_hold.wait(timeout=timeout)
    bob_transfer_hold.wait(timeout=timeout)

    alice_bob_channel_state = get_channelstate(alice_app, bob_app, token_network_identifier)
    alice_lock = channel.get_lock(alice_bob_channel_state.our_state, alice_transfer_secrethash)
    bob_lock = channel.get_lock(alice_bob_channel_state.partner_state, bob_transfer_secrethash)

    # This is the current state of protocol:
    #
    #    A -> B LockedTransfer
    #    - protocol didn't continue
    assert_synced_channel_state(
        token_network_identifier=token_network_identifier,
        app0=alice_app,
        balance0=deposit,
        pending_locks0=[alice_lock],
        app1=bob_app,
        balance1=deposit,
        pending_locks1=[bob_lock],
    )

    # A ChannelClose event will be generated, this will be polled by both apps
    # and each must start a task for calling settle
    RaidenAPI(bob_app.raiden).channel_close(
        registry_address=registry_address,
        token_address=token_address,
        partner_address=alice_app.raiden.address,
    )

    # wait for the close transaction to be mined, this is necessary to compute
    # the timeout for the settle
    with gevent.Timeout(timeout):
        waiting.wait_for_close(
            raiden=alice_app.raiden,
            payment_network_id=registry_address,
            token_address=token_address,
            channel_ids=[alice_bob_channel_state.identifier],
            retry_timeout=alice_app.raiden.alarm.sleep_time,
        )

    channel_closed = raiden_state_changes_search_for_item(
        bob_app.raiden,
        ContractReceiveChannelClosed,
        {
            "canonical_identifier": {
                "token_network_address": token_network_identifier,
                "channel_identifier": alice_bob_channel_state.identifier,
            }
        },
    )
    settle_max_wait_block = (
        channel_closed.block_number + alice_bob_channel_state.settle_timeout * 2
    )

    settle_timeout = BlockTimeout(
        RuntimeError("settle did not happen"),
        bob_app.raiden,
        settle_max_wait_block,
        alice_app.raiden.alarm.sleep_time,
    )
    with settle_timeout:
        waiting.wait_for_settle(
            raiden=alice_app.raiden,
            payment_network_id=registry_address,
            token_address=token_address,
            channel_ids=[alice_bob_channel_state.identifier],
            retry_timeout=alice_app.raiden.alarm.sleep_time,
        )

    with gevent.Timeout(timeout):
        wait_for_batch_unlock(
            app=bob_app,
            token_network_id=token_network_identifier,
            participant=alice_bob_channel_state.partner_state.address,
            partner=alice_bob_channel_state.our_state.address,
        )

    alice_app.start()

    with gevent.Timeout(timeout):
        wait_for_batch_unlock(
            app=alice_app,
            token_network_id=token_network_identifier,
            participant=alice_bob_channel_state.partner_state.address,
            partner=alice_bob_channel_state.our_state.address,
        )
예제 #17
0
def test_settled_lock(token_addresses, raiden_network, deposit):
    """ Any transfer following a secret revealed must update the locksroot, so
    hat an attacker cannot reuse a secret to double claim a lock."""
    app0, app1 = raiden_network
    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]
    amount = 30
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_registry.address,
        token_address,
    )

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

    deposit0 = deposit
    deposit1 = deposit

    token_proxy = app0.raiden.chain.token(token_address)
    initial_balance0 = token_proxy.balance_of(address0)
    initial_balance1 = token_proxy.balance_of(address1)

    # Using a pending mediated transfer because this allows us to compute the
    # merkle proof
    identifier = 1
    secret = pending_mediated_transfer(
        raiden_network,
        token_network_identifier,
        amount,
        identifier,
    )

    # Save the merkle tree leaves from the pending transfer, used to test the unlock
    channelstate_0_1 = get_channelstate(app0, app1, token_network_identifier)
    batch_unlock = channel.get_batch_unlock(channelstate_0_1.our_state)
    assert batch_unlock

    claim_lock(raiden_network, identifier, token_network_identifier, secret)

    # Make a new transfer
    direct_transfer(app0, app1, token_network_identifier, amount, identifier=1)
    RaidenAPI(app1.raiden).channel_close(
        registry_address,
        token_address,
        app0.raiden.address,
    )

    waiting.wait_for_settle(
        app1.raiden,
        app1.raiden.default_registry.address,
        token_address,
        [channelstate_0_1.identifier],
        app1.raiden.alarm.sleep_time,
    )

    netting_channel = app1.raiden.chain.payment_channel(
        token_network_identifier,
        channelstate_0_1.identifier,
    )

    # The direct transfer locksroot must not contain the unlocked lock, the
    # unlock must fail.
    with pytest.raises(Exception):
        netting_channel.unlock(
            channelstate_0_1.partner_state.address,
            batch_unlock,
        )

    expected_balance0 = initial_balance0 + deposit0 - amount * 2
    expected_balance1 = initial_balance1 + deposit1 + amount * 2

    assert token_proxy.balance_of(address0) == expected_balance0
    assert token_proxy.balance_of(address1) == expected_balance1
예제 #18
0
def test_settle_is_automatically_called(raiden_network, token_addresses):
    """Settle is automatically called by one of the nodes."""
    app0, app1 = raiden_network
    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]
    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_app(app0), app0.raiden.default_registry.address,
        token_address)
    assert token_network_address
    token_network = views.get_token_network_by_address(
        views.state_from_app(app0), token_network_address)
    assert token_network

    channel_identifier = get_channelstate(app0, app1,
                                          token_network_address).identifier

    assert (channel_identifier
            in token_network.partneraddresses_to_channelidentifiers[
                app1.raiden.address])

    # A ChannelClose event will be generated, this will be polled by both apps
    # and each must start a task for calling settle
    RaidenAPI(app1.raiden).channel_close(registry_address, token_address,
                                         app0.raiden.address)

    waiting.wait_for_close(
        app0.raiden,
        registry_address,
        token_address,
        [channel_identifier],
        app0.raiden.alarm.sleep_time,
    )

    channel_state = views.get_channelstate_for(
        views.state_from_raiden(app0.raiden), registry_address, token_address,
        app1.raiden.address)
    assert channel_state
    assert channel_state.close_transaction
    assert channel_state.close_transaction.finished_block_number

    waiting.wait_for_settle(
        app0.raiden,
        registry_address,
        token_address,
        [channel_identifier],
        app0.raiden.alarm.sleep_time,
    )

    token_network = views.get_token_network_by_address(
        views.state_from_app(app0), token_network_address)
    assert token_network

    assert (channel_identifier
            not in token_network.partneraddresses_to_channelidentifiers[
                app1.raiden.address])

    state_changes = app0.raiden.wal.storage.get_statechanges_by_range(
        RANGE_ALL_STATE_CHANGES)

    assert search_for_item(
        state_changes,
        ContractReceiveChannelClosed,
        {
            "token_network_address": token_network_address,
            "channel_identifier": channel_identifier,
            "transaction_from": app1.raiden.address,
            "block_number":
            channel_state.close_transaction.finished_block_number,
        },
    )

    assert search_for_item(
        state_changes,
        ContractReceiveChannelSettled,
        {
            "token_network_address": token_network_address,
            "channel_identifier": channel_identifier
        },
    )
예제 #19
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

    # The secret hasn't been revealed yet
    channel_state2_1 = get_channelstate(app2, app1, token_network_identifier)
    assert len(channel_state2_1.our_state.secrethashes_to_lockedlocks) == 1

    channel.register_secret(channel_state2_1, secret, secrethash)

    # Close the channel
    # This needs to register the secrets on chain
    netting_channel_proxy = app2.raiden.chain.payment_channel(
        token_network_identifier,
        channel_state2_1.identifier,
    )
    netting_channel_proxy.channel_close(
        registry_address,
        channel_state2_1.partner_state.balance_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,
        [],
    )
예제 #20
0
def test_settled_lock(token_addresses, raiden_network, deposit):
    """ Any transfer following a secret reveal must update the locksroot, so
    that an attacker cannot reuse a secret to double claim a lock.
    """
    app0, app1 = raiden_network
    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]
    amount = PaymentAmount(30)
    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_app(app0), app0.raiden.default_registry.address,
        token_address)
    assert token_network_address
    hold_event_handler = app1.raiden.raiden_event_handler

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

    deposit0 = deposit
    deposit1 = deposit

    token_proxy = app0.raiden.proxy_manager.token(token_address)
    initial_balance0 = token_proxy.balance_of(address0)
    initial_balance1 = token_proxy.balance_of(address1)
    identifier = 1
    target = app1.raiden.address
    secret = Secret(sha3(target))
    secrethash = sha256_secrethash(secret)

    secret_available = hold_event_handler.hold_secretrequest_for(
        secrethash=secrethash)

    app0.raiden.start_mediated_transfer_with_secret(
        token_network_address=token_network_address,
        amount=amount,
        target=target,
        identifier=identifier,
        secret=secret,
    )

    secret_available.wait()  # wait for the messages to be exchanged

    # Save the pending locks from the pending transfer, used to test the unlock
    channelstate_0_1 = get_channelstate(app0, app1, token_network_address)
    batch_unlock = channel.get_batch_unlock(channelstate_0_1.our_state)
    assert batch_unlock

    hold_event_handler.release_secretrequest_for(app1.raiden, secrethash)

    transfer(
        initiator_app=app0,
        target_app=app1,
        token_address=token_address,
        amount=amount,
        identifier=PaymentID(2),
    )

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

    waiting.wait_for_settle(
        app1.raiden,
        app1.raiden.default_registry.address,
        token_address,
        [channelstate_0_1.identifier],
        app1.raiden.alarm.sleep_time,
    )
    current_block = app0.raiden.rpc_client.block_number()

    netting_channel = app1.raiden.proxy_manager.payment_channel(
        canonical_identifier=channelstate_0_1.canonical_identifier)

    # The transfer locksroot must not contain the unlocked lock, the
    # unlock must fail.
    with pytest.raises(RaidenUnrecoverableError):
        netting_channel.unlock(
            sender=channelstate_0_1.our_state.address,
            receiver=channelstate_0_1.partner_state.address,
            pending_locks=batch_unlock,
            given_block_identifier=current_block,
        )

    expected_balance0 = initial_balance0 + deposit0 - amount * 2
    expected_balance1 = initial_balance1 + deposit1 + amount * 2

    assert token_proxy.balance_of(address0) == expected_balance0
    assert token_proxy.balance_of(address1) == expected_balance1
예제 #21
0
def test_channel_withdraw_expired(raiden_network, number_of_nodes,
                                  token_addresses, deposit, network_wait,
                                  retry_timeout):
    """ Tests withdraw expiration. """
    alice_app, bob_app = raiden_network
    token_address = token_addresses[0]
    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_app(alice_app),
        alice_app.raiden.default_registry.address, token_address)
    assert token_network_address

    # Prevent withdraw confirmation from being sent
    send_withdraw_confirmation_event = alice_app.raiden.raiden_event_handler.hold(
        SendWithdrawConfirmation, {})

    alice_to_bob_amount = 10
    total_withdraw = deposit + alice_to_bob_amount
    wait_for_withdraw_expired_message = alice_app.raiden.message_handler.wait_for_message(
        WithdrawExpired, {"total_withdraw": total_withdraw})

    identifier = 1
    target = bob_app.raiden.address
    secret = sha3(target)

    payment_status = alice_app.raiden.start_mediated_transfer_with_secret(
        token_network_address=token_network_address,
        amount=alice_to_bob_amount,
        target=target,
        identifier=identifier,
        secret=secret,
    )

    wait_for_unlock = bob_app.raiden.message_handler.wait_for_message(
        Unlock, {"payment_identifier": identifier})
    timeout = network_wait * number_of_nodes
    with Timeout(seconds=timeout):
        wait_for_unlock.get()
        msg = (
            f"transfer from {to_checksum_address(alice_app.raiden.address)} "
            f"to {to_checksum_address(bob_app.raiden.address)} failed.")
        assert payment_status.payment_done.get(), msg

    bob_alice_channel_state = get_channelstate(bob_app, alice_app,
                                               token_network_address)

    bob_app.raiden.withdraw(
        canonical_identifier=bob_alice_channel_state.canonical_identifier,
        total_withdraw=total_withdraw,
    )

    with Timeout(seconds=timeout):
        send_withdraw_confirmation_event.wait()

    # Make sure proper withdraw state is set in both channel states
    bob_alice_channel_state = get_channelstate(bob_app, alice_app,
                                               token_network_address)
    assert bob_alice_channel_state.our_total_withdraw == total_withdraw
    assert bob_alice_channel_state.our_state.withdraws_pending.get(
        total_withdraw) is not None

    alice_bob_channel_state = get_channelstate(alice_app, bob_app,
                                               token_network_address)
    assert alice_bob_channel_state.partner_total_withdraw == total_withdraw
    assert alice_bob_channel_state.partner_state.withdraws_pending.get(
        total_withdraw) is not None

    withdraw_expiration = bob_alice_channel_state.our_state.withdraws_pending[
        total_withdraw].expiration
    expiration_threshold = channel.get_sender_expiration_threshold(
        withdraw_expiration)

    waiting.wait_for_block(
        raiden=bob_app.raiden,
        block_number=BlockNumber(expiration_threshold + 1),
        retry_timeout=retry_timeout,
    )

    bob_alice_channel_state = get_channelstate(bob_app, alice_app,
                                               token_network_address)
    assert bob_alice_channel_state.our_total_withdraw == 0
    assert bob_alice_channel_state.our_state.withdraws_pending.get(
        total_withdraw) is None

    with Timeout(seconds=timeout):
        wait_for_withdraw_expired_message.wait()

        alice_bob_channel_state = get_channelstate(alice_app, bob_app,
                                                   token_network_address)
        assert alice_bob_channel_state.partner_total_withdraw == 0
        assert alice_bob_channel_state.partner_state.withdraws_pending.get(
            total_withdraw) is None
예제 #22
0
def test_batch_unlock(
    raiden_network: List[App],
    token_addresses: List[TokenAddress],
    secret_registry_address: SecretRegistryAddress,
    deposit: TokenAmount,
) -> None:
    """Tests that batch unlock is properly called.

    This test will start a single incomplete transfer, the secret will be
    revealed *on-chain*. The node that receives the tokens has to call unlock,
    the node that doesn't gain anything does nothing.
    """
    alice_app, bob_app = raiden_network
    alice_address = alice_app.raiden.address
    bob_address = bob_app.raiden.address

    token_network_registry_address = alice_app.raiden.default_registry.address
    token_address = token_addresses[0]
    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_app(alice_app), token_network_registry_address,
        token_address)
    assert token_network_address

    hold_event_handler = bob_app.raiden.raiden_event_handler
    assert isinstance(hold_event_handler, HoldRaidenEventHandler)

    # Take a snapshot early on
    alice_app.raiden.snapshot()

    canonical_identifier = get_channelstate(
        alice_app, bob_app, token_network_address).canonical_identifier

    assert is_channel_registered(alice_app, bob_app, canonical_identifier)
    assert is_channel_registered(bob_app, alice_app, canonical_identifier)

    token_proxy = alice_app.raiden.proxy_manager.token(token_address)
    alice_initial_balance = token_proxy.balance_of(alice_app.raiden.address)
    bob_initial_balance = token_proxy.balance_of(bob_app.raiden.address)

    # Take snapshot before transfer
    alice_app.raiden.snapshot()

    alice_to_bob_amount = 10
    identifier = 1
    secret = Secret(sha3(bob_address))
    secrethash = sha256_secrethash(secret)

    secret_request_event = hold_event_handler.hold_secretrequest_for(
        secrethash=secrethash)

    alice_app.raiden.start_mediated_transfer_with_secret(
        token_network_address=token_network_address,
        amount=PaymentAmount(alice_to_bob_amount),
        target=TargetAddress(bob_address),
        identifier=PaymentID(identifier),
        secret=secret,
    )

    secret_request_event.get()  # wait for the messages to be exchanged

    alice_bob_channel_state = get_channelstate(alice_app, bob_app,
                                               token_network_address)
    lock = channel.get_lock(alice_bob_channel_state.our_state, secrethash)
    assert lock

    # This is the current state of the protocol:
    #
    #    A -> B LockedTransfer
    #    B -> A SecretRequest
    #    - protocol didn't continue
    assert_synced_channel_state(token_network_address, alice_app,
                                Balance(deposit), [lock], bob_app,
                                Balance(deposit), [])

    # Test WAL restore to return the latest channel state
    alice_app.raiden.snapshot()
    our_balance_proof = alice_bob_channel_state.our_state.balance_proof
    restored_channel_state = channel_state_until_state_change(
        raiden=alice_app.raiden,
        canonical_identifier=alice_bob_channel_state.canonical_identifier,
        state_change_identifier=HIGH_STATECHANGE_ULID,
    )
    assert restored_channel_state
    our_restored_balance_proof = restored_channel_state.our_state.balance_proof
    assert our_balance_proof == our_restored_balance_proof

    # Close the channel before revealing the secret off-chain. This will leave
    # a pending lock in the channel which has to be unlocked on-chain.
    #
    # The token network will emit a ChannelClose event, this will be polled by
    # both apps and each must start a task for calling settle.
    RaidenAPI(bob_app.raiden).channel_close(token_network_registry_address,
                                            token_address,
                                            alice_app.raiden.address)

    # The secret has to be registered manually because Bob never learned the
    # secret. The test is holding the SecretRequest to ensure the off-chain
    # unlock will not happen and the channel is closed with a pending lock.
    #
    # Alternatives would be to hold the unlock messages, or to stop and restart
    # the apps after the channel is closed.
    secret_registry_proxy = alice_app.raiden.proxy_manager.secret_registry(
        secret_registry_address)
    secret_registry_proxy.register_secret(secret=secret)

    msg = (
        "The lock must still be part of the node state for the test to proceed, "
        "otherwise there is not unlock to be done.")
    assert lock, msg

    msg = (
        "The secret must be registered before the lock expires, in order for "
        "the unlock to happen on-chain. Otherwise the test will fail on the "
        "expected balances.")
    assert lock.expiration > alice_app.raiden.get_block_number(), msg
    assert lock.secrethash == sha256_secrethash(secret)

    waiting.wait_for_settle(
        alice_app.raiden,
        token_network_registry_address,
        token_address,
        [alice_bob_channel_state.identifier],
        alice_app.raiden.alarm.sleep_time,
    )

    msg = "The channel_state must not have been cleared, one of the ends has pending locks to do."
    assert is_channel_registered(alice_app, bob_app, canonical_identifier), msg
    assert is_channel_registered(bob_app, alice_app, canonical_identifier), msg

    msg = (
        "Timeout while waiting for the unlock to be mined. This may happen if "
        "transaction is rejected, not mined, or the node's alarm task is "
        "not running.")
    with gevent.Timeout(seconds=30, exception=AssertionError(msg)):
        # Wait for both nodes (Bob and Alice) to see the on-chain unlock
        wait_for_batch_unlock(
            app=alice_app,
            token_network_address=token_network_address,
            receiver=bob_address,
            sender=alice_address,
        )
        wait_for_batch_unlock(
            app=bob_app,
            token_network_address=token_network_address,
            receiver=bob_address,
            sender=alice_address,
        )

    msg = (
        "The nodes have done the unlock, and both ends have seen it, now the "
        "channel must be cleared")
    assert not is_channel_registered(alice_app, bob_app,
                                     canonical_identifier), msg
    assert not is_channel_registered(bob_app, alice_app,
                                     canonical_identifier), msg

    alice_new_balance = alice_initial_balance + deposit - alice_to_bob_amount
    bob_new_balance = bob_initial_balance + deposit + alice_to_bob_amount

    msg = "Unexpected end balance after channel settlement with batch unlock."
    assert token_proxy.balance_of(
        alice_app.raiden.address) == alice_new_balance, msg
    assert token_proxy.balance_of(
        bob_app.raiden.address) == bob_new_balance, msg
예제 #23
0
def test_different_view_of_last_bp_during_unlock(
        raiden_chain,
        number_of_nodes,
        token_addresses,
        deposit,
        network_wait,
        retry_timeout,
        # UDP does not seem to retry messages until processed
        # https://github.com/raiden-network/raiden/issues/3185
        skip_if_not_matrix,
):
    """Test for https://github.com/raiden-network/raiden/issues/3196#issuecomment-449163888"""
    # Topology:
    #
    #  0 -> 1 -> 2
    #
    app0, app1, app2 = raiden_chain
    token_address = token_addresses[0]
    payment_network_identifier = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        payment_network_identifier,
        token_address,
    )
    token_proxy = app0.raiden.chain.token(token_address)
    initial_balance0 = token_proxy.balance_of(app0.raiden.address)
    initial_balance1 = token_proxy.balance_of(app1.raiden.address)

    # make a transfer to test the path app0 -> app1 -> app2
    identifier_path = 1
    amount_path = 1
    mediated_transfer(
        app0,
        app2,
        token_network_identifier,
        amount_path,
        identifier_path,
        timeout=network_wait * number_of_nodes,
    )

    # drain the channel app1 -> app2
    identifier_drain = 2
    amount_drain = deposit * 8 // 10
    mediated_transfer(
        initiator_app=app1,
        target_app=app2,
        token_network_identifier=token_network_identifier,
        amount=amount_drain,
        identifier=identifier_drain,
        timeout=network_wait,
    )

    # wait for the nodes to sync
    gevent.sleep(0.2)

    assert_synced_channel_state(
        token_network_identifier,
        app0, deposit - amount_path, [],
        app1, deposit + amount_path, [],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1, deposit - amount_path - amount_drain, [],
        app2, deposit + amount_path + amount_drain, [],
    )

    # app0 -> app1 -> app2 is the only available path, but the channel app1 ->
    # app2 doesn't have capacity, so a refund will be sent on app1 -> app0
    identifier_refund = 3
    amount_refund = 50
    async_result = app0.raiden.mediated_transfer_async(
        token_network_identifier,
        amount_refund,
        app2.raiden.address,
        identifier_refund,
    )
    assert async_result.wait() is False, 'there is no path with capacity, the transfer must fail'

    gevent.sleep(0.2)

    # A lock structure with the correct amount

    send_locked = raiden_events_must_contain_entry(
        app0.raiden,
        SendLockedTransfer,
        {'transfer': {'lock': {'amount': amount_refund}}},
    )
    assert send_locked
    secrethash = send_locked.transfer.lock.secrethash

    send_refund = raiden_events_must_contain_entry(app1.raiden, SendRefundTransfer, {})
    assert send_refund

    lock = send_locked.transfer.lock
    refund_lock = send_refund.transfer.lock
    assert lock.amount == refund_lock.amount
    assert lock.secrethash
    assert lock.expiration
    assert lock.secrethash == refund_lock.secrethash

    # Both channels have the amount locked because of the refund message
    assert_synced_channel_state(
        token_network_identifier,
        app0, deposit - amount_path, [lockstate_from_lock(lock)],
        app1, deposit + amount_path, [lockstate_from_lock(refund_lock)],
    )
    assert_synced_channel_state(
        token_network_identifier,
        app1, deposit - amount_path - amount_drain, [],
        app2, deposit + amount_path + amount_drain, [],
    )

    # Additional checks for LockExpired causing nonce mismatch after refund transfer:
    # https://github.com/raiden-network/raiden/issues/3146#issuecomment-447378046
    # At this point make sure that the initiator has not deleted the payment task
    assert secrethash in state_from_raiden(app0.raiden).payment_mapping.secrethashes_to_task

    with dont_handle_node_change_network_state():
        # now app1 goes offline
        app1.raiden.stop()
        app1.raiden.get()
        assert not app1.raiden

        # Wait for lock expiration so that app0 sends a LockExpired
        wait_for_block(
            raiden=app0.raiden,
            block_number=channel.get_sender_expiration_threshold(lock) + 1,
            retry_timeout=retry_timeout,
        )

        # make sure that app0 sent a lock expired message for the secrethash
        wait_for_raiden_event(
            app0.raiden,
            SendLockExpired,
            {'secrethash': secrethash},
            retry_timeout,
        )

        # now app0 closes the channel
        RaidenAPI(app0.raiden).channel_close(
            registry_address=payment_network_identifier,
            token_address=token_address,
            partner_address=app1.raiden.address,
        )

    count = 0
    original_update = app1.raiden.raiden_event_handler.handle_contract_send_channelupdate

    def patched_update(raiden, event):
        nonlocal count
        count += 1
        original_update(raiden, event)

    app1.raiden.raiden_event_handler.handle_contract_send_channelupdate = patched_update
    # and now app1 comes back online
    app1.raiden.start()
    # test for https://github.com/raiden-network/raiden/issues/3216
    assert count == 1, 'Update transfer should have only been called once during restart'
    channel_identifier = get_channelstate(app0, app1, token_network_identifier).identifier

    # and we wait for settlement
    wait_for_settle(
        raiden=app0.raiden,
        payment_network_id=payment_network_identifier,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )

    with gevent.Timeout(10):
        unlock_app0 = wait_for_state_change(
            app0.raiden,
            ContractReceiveChannelBatchUnlock,
            {'participant': app0.raiden.address},
            retry_timeout,
        )
    assert unlock_app0.returned_tokens == 50
    with gevent.Timeout(10):
        unlock_app1 = wait_for_state_change(
            app1.raiden,
            ContractReceiveChannelBatchUnlock,
            {'participant': app1.raiden.address},
            retry_timeout,
        )
    assert unlock_app1.returned_tokens == 50
    final_balance0 = token_proxy.balance_of(app0.raiden.address)
    final_balance1 = token_proxy.balance_of(app1.raiden.address)

    assert final_balance0 - deposit - initial_balance0 == -1
    assert final_balance1 - deposit - initial_balance1 == 1
예제 #24
0
def test_batch_unlock(raiden_network, token_addresses, secret_registry_address, deposit):
    """Batch unlock can be called after the channel is settled."""
    alice_app, bob_app = raiden_network
    registry_address = alice_app.raiden.default_registry.address
    token_address = token_addresses[0]
    token_proxy = alice_app.raiden.chain.token(token_address)
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(alice_app),
        alice_app.raiden.default_registry.address,
        token_address,
    )

    alice_initial_balance = token_proxy.balance_of(alice_app.raiden.address)
    bob_initial_balance = token_proxy.balance_of(bob_app.raiden.address)

    alice_to_bob_amount = 10
    identifier = 1
    secret = pending_mediated_transfer(
        raiden_network,
        token_network_identifier,
        alice_to_bob_amount,
        identifier,
    )
    secrethash = sha3(secret)

    secret_registry_proxy = alice_app.raiden.chain.secret_registry(
        secret_registry_address,
    )
    secret_registry_proxy.register_secret(secret)

    alice_bob_channel_state = get_channelstate(alice_app, bob_app, token_network_identifier)
    lock = channel.get_lock(alice_bob_channel_state.our_state, secrethash)

    assert lock
    assert lock.expiration > alice_app.raiden.get_block_number()
    assert lock.secrethash == sha3(secret)

    # This is the current state of the protocol:
    #
    #    A -> B LockedTransfer
    #    B -> A SecretRequest
    #    - protocol didn't continue
    assert_synched_channel_state(
        token_network_identifier,
        alice_app, deposit, [lock],
        bob_app, deposit, [],
    )

    # A ChannelClose event will be generated, this will be polled by both apps
    # and each must start a task for calling settle
    RaidenAPI(bob_app.raiden).channel_close(
        registry_address,
        token_address,
        alice_app.raiden.address,
    )

    waiting.wait_for_settle(
        alice_app.raiden,
        registry_address,
        token_address,
        [alice_bob_channel_state.identifier],
        alice_app.raiden.alarm.sleep_time,
    )

    # wait for the node to call batch unlock
    with gevent.Timeout(10):
        wait_for_batch_unlock(
            alice_app,
            token_network_identifier,
            alice_bob_channel_state.partner_state.address,
            alice_bob_channel_state.our_state.address,
        )

    alice_new_balance = alice_initial_balance + deposit - alice_to_bob_amount
    bob_new_balance = bob_initial_balance + deposit + alice_to_bob_amount

    assert token_proxy.balance_of(alice_app.raiden.address) == alice_new_balance
    assert token_proxy.balance_of(bob_app.raiden.address) == bob_new_balance
예제 #25
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

    # 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(registry_address, token_address,
                                     api2.address)

    # Make sure invalid arguments to get_channel_list are caught
    with pytest.raises(UnknownTokenAddress):
        api1.get_channel_list(
            registry_address=registry_address,
            token_address=None,
            partner_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_blockchain_events_channel(
        token_address,
        channel12.partner_state.address,
    )
    assert any((event['event'] == ChannelEvent.OPENED and is_same_address(
        event['args']['participant1'],
        to_normalized_address(api1.address),
    ) and is_same_address(
        event['args']['participant2'],
        to_normalized_address(api2.address),
    )) for event in event_list1)

    token_events = api1.get_blockchain_events_token_network(token_address, )
    assert token_events[0]['event'] == ChannelEvent.OPENED

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

    # let's make sure it's idempotent. Same deposit should raise deposit mismatch limit
    with pytest.raises(DepositMismatch):
        api1.set_total_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_blockchain_events_channel(
        token_address,
        channel12.partner_state.address,
    )
    assert any((event['event'] == ChannelEvent.DEPOSIT and is_same_address(
        event['args']['participant'],
        to_normalized_address(api1.address),
    ) and event['args']['total_deposit'] == deposit) 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_blockchain_events_channel(
        token_address,
        channel12.partner_state.address,
    )
    assert len(event_list3) > len(event_list2)
    assert any((event['event'] == ChannelEvent.CLOSED and is_same_address(
        event['args']['closing_participant'],
        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)

    state_changes = node1.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )

    assert must_contain_entry(
        state_changes, ContractReceiveChannelSettled, {
            'token_network_identifier': token_network_identifier,
            'channel_identifier': channel12.identifier,
        })
예제 #26
0
def test_receive_lockedtransfer_invalidnonce(
    raiden_network: List[RaidenService],
    number_of_nodes,
    deposit,
    token_addresses,
    reveal_timeout,
    network_wait,
):
    app0, app1, app2 = raiden_network
    token_address = token_addresses[0]
    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_raiden(app0), app0.default_registry.address, token_address
    )
    assert token_network_address
    channel0 = get_channelstate(app0, app1, token_network_address)

    amount = 10
    payment_identifier = PaymentID(1)
    secrethash = transfer(
        initiator_app=app0,
        target_app=app2,
        token_address=token_address,
        amount=PaymentAmount(10),
        identifier=payment_identifier,
        timeout=network_wait * number_of_nodes,
        routes=[[app0.address, app1.address, app2.address]],
    )

    repeated_nonce = Nonce(1)
    expiration = reveal_timeout * 2
    mediated_transfer_message = LockedTransfer(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=make_message_identifier(),
        payment_identifier=payment_identifier,
        nonce=repeated_nonce,
        token_network_address=token_network_address,
        token=token_address,
        channel_identifier=channel0.identifier,
        transferred_amount=TokenAmount(amount),
        locked_amount=LockedAmount(amount),
        recipient=app1.address,
        locksroot=make_locksroot(),
        lock=Lock(
            amount=PaymentWithFeeAmount(amount), expiration=expiration, secrethash=UNIT_SECRETHASH
        ),
        target=TargetAddress(app2.address),
        initiator=InitiatorAddress(app0.address),
        signature=EMPTY_SIGNATURE,
        metadata=Metadata(routes=[RouteMetadata(route=[app1.address, app2.address])]),
    )

    sign_and_inject(mediated_transfer_message, app0.signer, app1)

    with block_timeout_for_transfer_by_secrethash(app1, secrethash):
        wait_assert(
            assert_synced_channel_state,
            token_network_address,
            app0,
            deposit - amount,
            [],
            app1,
            deposit + amount,
            [],
        )
예제 #27
0
def test_automatic_dispute(raiden_network, deposit, token_addresses):
    app0, app1 = raiden_network
    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,
    )

    channel0 = get_channelstate(app0, app1, token_network_identifier)
    token_proxy = app0.raiden.chain.token(channel0.token_address)
    initial_balance0 = token_proxy.balance_of(app0.raiden.address)
    initial_balance1 = token_proxy.balance_of(app1.raiden.address)

    amount0_1 = 10
    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=amount0_1,
    )

    amount1_1 = 50
    mediated_transfer(
        initiator_app=app1,
        target_app=app0,
        token_network_identifier=token_network_identifier,
        amount=amount1_1,
    )

    amount0_2 = 60
    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=amount0_2,
    )

    # Alice can only provide one of Bob's transfer, so she is incentivized to
    # use the one with the largest transferred_amount.
    RaidenAPI(app0.raiden).channel_close(
        registry_address,
        token_address,
        app1.raiden.address,
    )

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

    waiting.wait_for_settle(
        app0.raiden,
        registry_address,
        token_address,
        [channel0.identifier],
        app0.raiden.alarm.sleep_time,
    )

    # check that the channel is properly settled and that Bob's client
    # automatically called updateTransfer() to reflect the actual transactions
    assert token_proxy.balance_of(token_network_identifier) == 0
    total0 = amount0_1 + amount0_2
    total1 = amount1_1
    expected_balance0 = initial_balance0 + deposit - total0 + total1
    expected_balance1 = initial_balance1 + deposit + total0 - total1
    assert token_proxy.balance_of(app0.raiden.address) == expected_balance0
    assert token_proxy.balance_of(app1.raiden.address) == expected_balance1
예제 #28
0
def test_receive_lockedtransfer_invalidnonce(
    raiden_network,
    deposit,
    token_addresses,
    reveal_timeout,
    network_wait,
):

    app0, app1, app2 = raiden_network
    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,
    )
    channel0 = get_channelstate(app0, app1, token_network_identifier)

    amount = 10
    mediated_transfer(
        app0,
        app2,
        token_network_identifier,
        amount,
        timeout=network_wait,
    )

    amount = 10
    payment_identifier = 1
    repeated_nonce = 1
    expiration = reveal_timeout * 2
    mediated_transfer_message = LockedTransfer(
        message_identifier=random.randint(0, UINT64_MAX),
        payment_identifier=payment_identifier,
        nonce=repeated_nonce,
        token_network_address=token_network_identifier,
        token=token_address,
        channel=channel0.identifier,
        transferred_amount=amount,
        locked_amount=amount,
        recipient=app1.raiden.address,
        locksroot=UNIT_SECRETHASH,
        lock=Lock(amount, expiration, UNIT_SECRETHASH),
        target=app2.raiden.address,
        initiator=app0.raiden.address,
        fee=0,
    )

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

    wait_assert(
        token_network_identifier,
        app0,
        deposit - amount,
        [],
        app1,
        deposit + amount,
        [],
        func=assert_synched_channel_state,
        timeout=network_wait,
    )
예제 #29
0
def test_regression_multiple_revealsecret(raiden_network, token_addresses,
                                          transport_protocol):
    """ Multiple RevealSecret messages arriving at the same time must be
    handled properly.

    Secret handling followed these steps:

        The Secret message arrives
        The secret is registered
        The channel is updated and the correspoding lock is removed
        * A balance proof for the new channel state is created and sent to the
          payer
        The channel is unregistered for the given secrethash

    The step marked with an asterisk above introduced a context-switch. This
    allowed a second Reveal Secret message to be handled before the channel was
    unregistered. And because the channel was already updated an exception was raised
    for an unknown secret.
    """
    app0, app1 = raiden_network
    token = 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,
    )
    channelstate_0_1 = get_channelstate(app0, app1, token_network_identifier)

    payment_identifier = 1
    secret = sha3(b'test_regression_multiple_revealsecret')
    secrethash = sha3(secret)
    expiration = app0.raiden.get_block_number() + 100
    lock_amount = 10
    lock = Lock(
        lock_amount,
        expiration,
        secrethash,
    )

    nonce = 1
    transferred_amount = 0
    mediated_transfer = LockedTransfer(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=random.randint(0, UINT64_MAX),
        payment_identifier=payment_identifier,
        nonce=nonce,
        token_network_address=app0.raiden.default_registry.address,
        token=token,
        channel_identifier=channelstate_0_1.identifier,
        transferred_amount=transferred_amount,
        locked_amount=lock_amount,
        recipient=app1.raiden.address,
        locksroot=lock.secrethash,
        lock=lock,
        target=app1.raiden.address,
        initiator=app0.raiden.address,
    )
    app0.raiden.sign(mediated_transfer)

    if transport_protocol is TransportProtocol.UDP:
        message_data = mediated_transfer.encode()
        host_port = None
        app1.raiden.transport.receive(message_data, host_port)
    elif transport_protocol is TransportProtocol.MATRIX:
        app1.raiden.transport._receive_message(mediated_transfer)
    else:
        raise TypeError('Unknown TransportProtocol')

    reveal_secret = RevealSecret(
        random.randint(0, UINT64_MAX),
        secret,
    )
    app0.raiden.sign(reveal_secret)

    token_network_identifier = channelstate_0_1.token_network_identifier
    secret = Secret(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=random.randint(0, UINT64_MAX),
        payment_identifier=payment_identifier,
        nonce=mediated_transfer.nonce + 1,
        token_network_address=token_network_identifier,
        channel_identifier=channelstate_0_1.identifier,
        transferred_amount=lock_amount,
        locked_amount=0,
        locksroot=EMPTY_MERKLE_ROOT,
        secret=secret,
    )
    app0.raiden.sign(secret)

    if transport_protocol is TransportProtocol.UDP:
        messages = [
            secret.encode(),
            reveal_secret.encode(),
        ]
        host_port = None
        receive_method = app1.raiden.transport.receive
        wait = [
            gevent.spawn_later(
                .1,
                receive_method,
                data,
                host_port,
            ) for data in messages
        ]
    elif transport_protocol is TransportProtocol.MATRIX:
        messages = [
            secret,
            reveal_secret,
        ]
        receive_method = app1.raiden.transport._receive_message
        wait = [
            gevent.spawn_later(
                .1,
                receive_method,
                data,
            ) for data in messages
        ]
    else:
        raise TypeError('Unknown TransportProtocol')

    gevent.joinall(wait)
예제 #30
0
def test_batch_unlock(raiden_network, token_addresses, secret_registry_address, deposit):
    """Batch unlock can be called after the channel is settled."""
    alice_app, bob_app = raiden_network
    registry_address = alice_app.raiden.default_registry.address
    token_address = token_addresses[0]
    token_proxy = alice_app.raiden.chain.token(token_address)
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(alice_app),
        alice_app.raiden.default_registry.address,
        token_address,
    )

    alice_initial_balance = token_proxy.balance_of(alice_app.raiden.address)
    bob_initial_balance = token_proxy.balance_of(bob_app.raiden.address)

    alice_to_bob_amount = 10
    identifier = 1
    secret = pending_mediated_transfer(
        raiden_network,
        token_network_identifier,
        alice_to_bob_amount,
        identifier,
    )
    secrethash = sha3(secret)

    secret_registry_proxy = alice_app.raiden.chain.secret_registry(
        secret_registry_address,
    )
    secret_registry_proxy.register_secret(secret)

    alice_bob_channel_state = get_channelstate(alice_app, bob_app, token_network_identifier)
    lock = channel.get_lock(alice_bob_channel_state.our_state, secrethash)

    assert lock
    assert lock.expiration > alice_app.raiden.get_block_number()
    assert lock.secrethash == sha3(secret)

    # This is the current state of the protocol:
    #
    #    A -> B LockedTransfer
    #    B -> A SecretRequest
    #    - protocol didn't continue
    assert_synched_channel_state(
        token_network_identifier,
        alice_app, deposit, [lock],
        bob_app, deposit, [],
    )

    # A ChannelClose event will be generated, this will be polled by both apps
    # and each must start a task for calling settle
    RaidenAPI(bob_app.raiden).channel_close(
        registry_address,
        token_address,
        alice_app.raiden.address,
    )

    waiting.wait_for_settle(
        alice_app.raiden,
        registry_address,
        token_address,
        [alice_bob_channel_state.identifier],
        alice_app.raiden.alarm.wait_time,
    )

    # wait for the node to call batch unlock
    with gevent.Timeout(10):
        wait_for_batch_unlock(
            alice_app,
            alice_bob_channel_state.identifier,
            token_network_identifier,
        )

    alice_new_balance = alice_initial_balance + deposit - alice_to_bob_amount
    bob_new_balance = bob_initial_balance + deposit + alice_to_bob_amount

    assert token_proxy.balance_of(alice_app.raiden.address) == alice_new_balance
    assert token_proxy.balance_of(bob_app.raiden.address) == bob_new_balance
예제 #31
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]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_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 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,
        token_network_address=token_network_identifier,
        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_network_identifier,
        app0,
        deposit,
        [],
        app1,
        deposit,
        [],
    )
예제 #32
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

    # 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(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.set_total_channel_deposit(
        registry_address,
        token_address,
        api2.address,
        deposit,
    )
    # let's make sure it's idempotent
    api1.set_total_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
예제 #33
0
def test_regression_multiple_revealsecret(raiden_network, token_addresses, transport_protocol):
    """ Multiple RevealSecret messages arriving at the same time must be
    handled properly.

    Secret handling followed these steps:

        The Secret message arrives
        The secret is registered
        The channel is updated and the correspoding lock is removed
        * A balance proof for the new channel state is created and sent to the
          payer
        The channel is unregistered for the given secrethash

    The step marked with an asterisk above introduced a context-switch. This
    allowed a second Reveal Secret message to be handled before the channel was
    unregistered. And because the channel was already updated an exception was raised
    for an unknown secret.
    """
    app0, app1 = raiden_network
    token = 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,
    )
    channelstate_0_1 = get_channelstate(app0, app1, token_network_identifier)

    payment_identifier = 1
    secret = sha3(b'test_regression_multiple_revealsecret')
    secrethash = sha3(secret)
    expiration = app0.raiden.get_block_number() + 100
    lock_amount = 10
    lock = Lock(
        lock_amount,
        expiration,
        secrethash,
    )

    nonce = 1
    transferred_amount = 0
    mediated_transfer = LockedTransfer(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=random.randint(0, UINT64_MAX),
        payment_identifier=payment_identifier,
        nonce=nonce,
        token_network_address=app0.raiden.default_registry.address,
        token=token,
        channel_identifier=channelstate_0_1.identifier,
        transferred_amount=transferred_amount,
        locked_amount=lock_amount,
        recipient=app1.raiden.address,
        locksroot=lock.secrethash,
        lock=lock,
        target=app1.raiden.address,
        initiator=app0.raiden.address,
    )
    app0.raiden.sign(mediated_transfer)

    if transport_protocol is TransportProtocol.UDP:
        message_data = mediated_transfer.encode()
        host_port = None
        app1.raiden.transport.receive(message_data, host_port)
    elif transport_protocol is TransportProtocol.MATRIX:
        app1.raiden.transport._receive_message(mediated_transfer)
    else:
        raise TypeError('Unknown TransportProtocol')

    reveal_secret = RevealSecret(
        random.randint(0, UINT64_MAX),
        secret,
    )
    app0.raiden.sign(reveal_secret)

    token_network_identifier = channelstate_0_1.token_network_identifier
    secret = Secret(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=random.randint(0, UINT64_MAX),
        payment_identifier=payment_identifier,
        nonce=mediated_transfer.nonce + 1,
        token_network_address=token_network_identifier,
        channel_identifier=channelstate_0_1.identifier,
        transferred_amount=lock_amount,
        locked_amount=0,
        locksroot=EMPTY_MERKLE_ROOT,
        secret=secret,
    )
    app0.raiden.sign(secret)

    if transport_protocol is TransportProtocol.UDP:
        messages = [
            secret.encode(),
            reveal_secret.encode(),
        ]
        host_port = None
        receive_method = app1.raiden.transport.receive
        wait = [
            gevent.spawn_later(
                .1,
                receive_method,
                data,
                host_port,
            )
            for data in messages
        ]
    elif transport_protocol is TransportProtocol.MATRIX:
        messages = [
            secret,
            reveal_secret,
        ]
        receive_method = app1.raiden.transport._receive_message
        wait = [
            gevent.spawn_later(
                .1,
                receive_method,
                data,
            )
            for data in messages
        ]
    else:
        raise TypeError('Unknown TransportProtocol')

    gevent.joinall(wait)
예제 #34
0
def test_unlock(raiden_network, token_addresses, deposit):
    """Unlock can be called on a closed channel."""
    alice_app, bob_app = raiden_network
    registry_address = alice_app.raiden.default_registry.address
    token_address = token_addresses[0]
    token_proxy = alice_app.raiden.chain.token(token_address)
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(alice_app),
        alice_app.raiden.default_registry.address,
        token_address,
    )

    alice_initial_balance = token_proxy.balance_of(alice_app.raiden.address)
    bob_initial_balance = token_proxy.balance_of(bob_app.raiden.address)

    alice_to_bob_amount = 10
    identifier = 1
    secret = pending_mediated_transfer(
        raiden_network,
        token_network_identifier,
        alice_to_bob_amount,
        identifier,
    )
    secrethash = sha3(secret)

    # This is the current state of the protocol:
    #
    #    A -> B LockedTransfer
    #    B -> A SecretRequest
    #    - protocol didn't continue

    alice_bob_channel = get_channelstate(alice_app, bob_app,
                                         token_network_identifier)
    bob_alice_channel = get_channelstate(bob_app, alice_app,
                                         token_network_identifier)

    lock = channel.get_lock(alice_bob_channel.our_state, secrethash)
    assert lock

    assert_synched_channel_state(
        token_network_identifier,
        alice_app,
        deposit,
        [lock],
        bob_app,
        deposit,
        [],
    )

    # get proof, that locked transfermessage was in merkle tree, with locked.root
    unlock_proof = channel.compute_proof_for_lock(
        alice_bob_channel.our_state,
        secret,
        lock,
    )

    assert validate_proof(
        unlock_proof.merkle_proof,
        merkleroot(bob_alice_channel.partner_state.merkletree),
        sha3(lock.encoded),
    )
    assert unlock_proof.lock_encoded == lock.encoded
    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
    RaidenAPI(bob_app.raiden).channel_close(
        registry_address,
        token_address,
        alice_app.raiden.address,
    )

    # Unlock will not be called because the secret was not revealed
    assert lock.expiration > alice_app.raiden.chain.block_number()
    assert lock.secrethash == sha3(secret)

    nettingchannel_proxy = bob_app.raiden.chain.netting_channel(
        bob_alice_channel.identifier, )
    nettingchannel_proxy.unlock(unlock_proof)

    waiting.wait_for_settle(
        alice_app.raiden,
        registry_address,
        token_address,
        [alice_bob_channel.identifier],
        alice_app.raiden.alarm.wait_time,
    )

    alice_bob_channel = get_channelstate(alice_app, bob_app,
                                         token_network_identifier)
    bob_alice_channel = get_channelstate(bob_app, alice_app,
                                         token_network_identifier)

    alice_netted_balance = alice_initial_balance + deposit - alice_to_bob_amount
    bob_netted_balance = bob_initial_balance + deposit + alice_to_bob_amount

    assert token_proxy.balance_of(
        alice_app.raiden.address) == alice_netted_balance
    assert token_proxy.balance_of(bob_app.raiden.address) == bob_netted_balance

    # Now let's query the WAL to see if the state changes were logged as expected
    state_changes = alice_app.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )

    alice_bob_channel = get_channelstate(alice_app, bob_app,
                                         token_network_identifier)
    bob_alice_channel = get_channelstate(bob_app, alice_app,
                                         token_network_identifier)

    assert must_contain_entry(
        state_changes, ContractReceiveChannelUnlock, {
            'payment_network_identifier': registry_address,
            'token_address': token_address,
            'channel_identifier': alice_bob_channel.identifier,
            'secrethash': secrethash,
            'secret': secret,
            'receiver': bob_app.raiden.address,
        })
예제 #35
0
def run_test_batch_unlock(
    raiden_network,
    token_addresses,
    secret_registry_address,
    deposit,
    blockchain_type,
):
    """Batch unlock can be called after the channel is settled."""
    alice_app, bob_app = raiden_network
    registry_address = alice_app.raiden.default_registry.address
    token_address = token_addresses[0]
    token_proxy = alice_app.raiden.chain.token(token_address)
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(alice_app),
        alice_app.raiden.default_registry.address,
        token_address,
    )

    hold_event_handler = HoldOffChainSecretRequest()
    bob_app.raiden.raiden_event_handler = hold_event_handler

    # Take a snapshot early on
    alice_app.raiden.wal.snapshot()

    token_network = views.get_token_network_by_identifier(
        views.state_from_app(alice_app),
        token_network_identifier,
    )

    channel_identifier = get_channelstate(alice_app, bob_app,
                                          token_network_identifier).identifier

    assert channel_identifier in token_network.partneraddresses_to_channelidentifiers[
        bob_app.raiden.address]

    alice_initial_balance = token_proxy.balance_of(alice_app.raiden.address)
    bob_initial_balance = token_proxy.balance_of(bob_app.raiden.address)

    # Take snapshot before transfer
    alice_app.raiden.wal.snapshot()

    alice_to_bob_amount = 10
    identifier = 1
    target = bob_app.raiden.address
    secret = sha3(target)
    secrethash = sha3(secret)

    hold_event_handler.hold_secretrequest_for(secrethash=secrethash)

    alice_app.raiden.start_mediated_transfer_with_secret(
        token_network_identifier=token_network_identifier,
        amount=alice_to_bob_amount,
        fee=0,
        target=target,
        identifier=identifier,
        secret=secret,
    )

    gevent.sleep(1)  # wait for the messages to be exchanged

    alice_bob_channel_state = get_channelstate(alice_app, bob_app,
                                               token_network_identifier)
    lock = channel.get_lock(alice_bob_channel_state.our_state, secrethash)

    # This is the current state of the protocol:
    #
    #    A -> B LockedTransfer
    #    B -> A SecretRequest
    #    - protocol didn't continue
    assert_synced_channel_state(
        token_network_identifier,
        alice_app,
        deposit,
        [lock],
        bob_app,
        deposit,
        [],
    )

    # Take a snapshot early on
    alice_app.raiden.wal.snapshot()

    our_balance_proof = alice_bob_channel_state.our_state.balance_proof

    # Test WAL restore to return the latest channel state
    restored_channel_state = channel_state_until_state_change(
        raiden=alice_app.raiden,
        payment_network_identifier=alice_app.raiden.default_registry.address,
        token_address=token_address,
        channel_identifier=alice_bob_channel_state.identifier,
        state_change_identifier='latest',
    )

    our_restored_balance_proof = restored_channel_state.our_state.balance_proof
    assert our_balance_proof == our_restored_balance_proof

    # A ChannelClose event will be generated, this will be polled by both apps
    # and each must start a task for calling settle
    RaidenAPI(bob_app.raiden).channel_close(
        registry_address,
        token_address,
        alice_app.raiden.address,
    )

    secret_registry_proxy = alice_app.raiden.chain.secret_registry(
        secret_registry_address, )
    secret_registry_proxy.register_secret(secret=secret,
                                          given_block_identifier='latest')

    assert lock, 'the lock must still be part of the node state'
    msg = 'the secret must be registered before the lock expires'
    assert lock.expiration > alice_app.raiden.get_block_number(), msg
    assert lock.secrethash == sha3(secret)

    waiting.wait_for_settle(
        alice_app.raiden,
        registry_address,
        token_address,
        [alice_bob_channel_state.identifier],
        alice_app.raiden.alarm.sleep_time,
    )

    token_network = views.get_token_network_by_identifier(
        views.state_from_app(bob_app),
        token_network_identifier,
    )

    assert channel_identifier in token_network.partneraddresses_to_channelidentifiers[
        alice_app.raiden.address]

    # wait for the node to call batch unlock
    timeout = 30 if blockchain_type == 'parity' else 10
    with gevent.Timeout(timeout):
        wait_for_batch_unlock(
            bob_app,
            token_network_identifier,
            alice_bob_channel_state.partner_state.address,
            alice_bob_channel_state.our_state.address,
        )

    token_network = views.get_token_network_by_identifier(
        views.state_from_app(bob_app),
        token_network_identifier,
    )

    assert channel_identifier not in token_network.partneraddresses_to_channelidentifiers[
        alice_app.raiden.address]

    alice_new_balance = alice_initial_balance + deposit - alice_to_bob_amount
    bob_new_balance = bob_initial_balance + deposit + alice_to_bob_amount

    assert token_proxy.balance_of(
        alice_app.raiden.address) == alice_new_balance
    assert token_proxy.balance_of(bob_app.raiden.address) == bob_new_balance
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]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_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 mediated transfer for the closed channel
    lock_amount = 10
    payment_identifier = 1
    expiration = reveal_timeout * 2
    mediated_transfer_message = LockedTransfer(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=random.randint(0, UINT64_MAX),
        payment_identifier=payment_identifier,
        nonce=1,
        token_network_address=token_network_identifier,
        token=token_address,
        channel_identifier=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_synced_channel_state(
        token_network_identifier,
        app0, deposit, [],
        app1, deposit, [],
    )
예제 #37
0
def run_test_settle_is_automatically_called(raiden_network, token_addresses):
    """Settle is automatically called by one of the nodes."""
    app0, app1 = raiden_network
    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,
    )
    token_network = views.get_token_network_by_identifier(
        views.state_from_app(app0),
        token_network_identifier,
    )

    channel_identifier = get_channelstate(app0, app1,
                                          token_network_identifier).identifier

    assert channel_identifier in token_network.partneraddresses_to_channelidentifiers[
        app1.raiden.address]

    # A ChannelClose event will be generated, this will be polled by both apps
    # and each must start a task for calling settle
    RaidenAPI(app1.raiden).channel_close(
        registry_address,
        token_address,
        app0.raiden.address,
    )

    waiting.wait_for_close(
        app0.raiden,
        registry_address,
        token_address,
        [channel_identifier],
        app0.raiden.alarm.sleep_time,
    )

    channel_state = views.get_channelstate_for(
        views.state_from_raiden(app0.raiden),
        registry_address,
        token_address,
        app1.raiden.address,
    )

    assert channel_state.close_transaction.finished_block_number

    waiting.wait_for_settle(
        app0.raiden,
        registry_address,
        token_address,
        [channel_identifier],
        app0.raiden.alarm.sleep_time,
    )

    token_network = views.get_token_network_by_identifier(
        views.state_from_app(app0),
        token_network_identifier,
    )

    assert channel_identifier not in token_network.partneraddresses_to_channelidentifiers[
        app1.raiden.address]

    state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )

    assert search_for_item(
        state_changes,
        ContractReceiveChannelClosed,
        {
            'token_network_identifier': token_network_identifier,
            'channel_identifier': channel_identifier,
            'transaction_from': app1.raiden.address,
            'block_number':
            channel_state.close_transaction.finished_block_number,
        },
    )

    assert search_for_item(
        state_changes,
        ContractReceiveChannelSettled,
        {
            'token_network_identifier': token_network_identifier,
            'channel_identifier': channel_identifier,
        },
    )
예제 #38
0
def test_channel_deposit(raiden_chain, deposit, retry_timeout, token_addresses):
    app0, app1 = raiden_chain
    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),
        app0.raiden.default_registry.address,
        token_address,
    )

    channel0 = get_channelstate(app0, app1, token_network_identifier)
    channel1 = get_channelstate(app1, app0, token_network_identifier)
    assert channel0 is None
    assert channel1 is None

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

    wait_both_channel_open(app0, app1, registry_address, token_address, retry_timeout)

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

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

    wait_both_channel_deposit(
        app0,
        app1,
        registry_address,
        token_address,
        deposit,
        retry_timeout,
    )

    assert_synced_channel_state(
        token_network_identifier,
        app0, deposit, [],
        app1, 0, [],
    )

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

    wait_both_channel_deposit(
        app1,
        app0,
        registry_address,
        token_address,
        deposit,
        retry_timeout,
    )

    assert_synced_channel_state(
        token_network_identifier,
        app0, deposit, [],
        app1, deposit, [],
    )
예제 #39
0
def run_test_automatic_dispute(raiden_network, deposit, token_addresses):
    app0, app1 = raiden_network
    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,
    )

    channel0 = get_channelstate(app0, app1, token_network_identifier)
    token_proxy = app0.raiden.chain.token(channel0.token_address)
    initial_balance0 = token_proxy.balance_of(app0.raiden.address)
    initial_balance1 = token_proxy.balance_of(app1.raiden.address)

    amount0_1 = 10
    transfer(
        initiator_app=app0,
        target_app=app1,
        token_address=token_address,
        amount=amount0_1,
        identifier=1,
    )

    amount1_1 = 50
    transfer(
        initiator_app=app1,
        target_app=app0,
        token_address=token_address,
        amount=amount1_1,
        identifier=2,
    )

    amount0_2 = 60
    transfer(
        initiator_app=app0,
        target_app=app1,
        token_address=token_address,
        amount=amount0_2,
        identifier=3,
    )

    # Alice can only provide one of Bob's transfer, so she is incentivized to
    # use the one with the largest transferred_amount.
    RaidenAPI(app0.raiden).channel_close(
        registry_address,
        token_address,
        app1.raiden.address,
    )

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

    waiting.wait_for_settle(
        app0.raiden,
        registry_address,
        token_address,
        [channel0.identifier],
        app0.raiden.alarm.sleep_time,
    )

    # check that the channel is properly settled and that Bob's client
    # automatically called updateTransfer() to reflect the actual transactions
    assert token_proxy.balance_of(token_network_identifier) == 0
    total0 = amount0_1 + amount0_2
    total1 = amount1_1
    expected_balance0 = initial_balance0 + deposit - total0 + total1
    expected_balance1 = initial_balance1 + deposit + total0 - total1
    assert token_proxy.balance_of(app0.raiden.address) == expected_balance0
    assert token_proxy.balance_of(app1.raiden.address) == expected_balance1
예제 #40
0
def test_clear_closed_queue(raiden_network, token_addresses, deposit, network_wait):
    """ Closing a channel clears the respective message queue. """
    app0, app1 = raiden_network
    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]
    chain_state0 = views.state_from_app(app0)
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state0,
        app0.raiden.default_registry.address,
        token_address,
    )
    token_network = views.get_token_network_by_identifier(
        chain_state0,
        token_network_identifier,
    )

    channel_identifier = get_channelstate(app0, app1, token_network_identifier).identifier

    assert channel_identifier in token_network.partneraddresses_to_channelidentifiers[
        app1.raiden.address
    ]

    with dont_handle_secret_request_mock(app0):
        # make an unconfirmed transfer to ensure the nodes have communicated
        amount = 10
        payment_identifier = 1337
        app0.raiden.mediated_transfer_async(
            token_network_identifier=token_network_identifier,
            amount=amount,
            target=app1.raiden.address,
            identifier=payment_identifier,
        )

        app1.raiden.transport.stop()
        app1.raiden.transport.get()

        # make sure to wait until the queue is created
        def has_initiator_events():
            initiator_events = app0.raiden.wal.storage.get_events()
            return must_contain_entry(initiator_events, SendLockedTransfer, {})

        assert wait_until(has_initiator_events, network_wait)

    # assert the specific queue is present
    chain_state0 = views.state_from_app(app0)
    queues0 = views.get_all_messagequeues(chain_state=chain_state0)
    assert [
        (queue_id, queue)
        for queue_id, queue in queues0.items()
        if queue_id.recipient == app1.raiden.address and
        queue_id.channel_identifier == channel_identifier and queue
    ]

    # A ChannelClose event will be generated, this will be polled by both apps
    RaidenAPI(app0.raiden).channel_close(
        registry_address,
        token_address,
        app1.raiden.address,
    )

    exception = ValueError('Could not get close event')
    with gevent.Timeout(seconds=30, exception=exception):
        waiting.wait_for_close(
            app0.raiden,
            registry_address,
            token_address,
            [channel_identifier],
            app0.raiden.alarm.sleep_time,
        )

    # assert all queues with this partner are gone or empty
    chain_state0 = views.state_from_app(app0)
    queues0 = views.get_all_messagequeues(chain_state=chain_state0)
    assert not [
        (queue_id, queue)
        for queue_id, queue in queues0.items()
        if queue_id.recipient == app1.raiden.address and queue
    ]

    chain_state1 = views.state_from_app(app1)
    queues1 = views.get_all_messagequeues(chain_state=chain_state1)
    assert not [
        (queue_id, queue)
        for queue_id, queue in queues1.items()
        if queue_id.recipient == app0.raiden.address and queue
    ]
예제 #41
0
def test_channel_lifecycle(raiden_network, token_addresses, deposit, transport_protocol):
    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

    # 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(registry_address, token_address, api2.address)

    # Make sure invalid arguments to get_channel_list are caught
    with pytest.raises(UnknownTokenAddress):
        api1.get_channel_list(
            registry_address=registry_address,
            token_address=None,
            partner_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_blockchain_events_channel(
        token_address,
        channel12.partner_state.address,
    )
    assert any(
        (
            event['event'] == ChannelEvent.OPENED and
            is_same_address(
                event['args']['participant1'],
                to_normalized_address(api1.address),
            ) and
            is_same_address(
                event['args']['participant2'],
                to_normalized_address(api2.address),
            )
        )
        for event in event_list1
    )

    token_events = api1.get_blockchain_events_token_network(
        token_address,
    )
    assert token_events[0]['event'] == ChannelEvent.OPENED

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

    # let's make sure it's idempotent. Same deposit should raise deposit mismatch limit
    with pytest.raises(DepositMismatch):
        api1.set_total_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_blockchain_events_channel(
        token_address,
        channel12.partner_state.address,
    )
    assert any(
        (
            event['event'] == ChannelEvent.DEPOSIT and
            is_same_address(
                event['args']['participant'],
                to_normalized_address(api1.address),
            ) and
            event['args']['total_deposit'] == deposit
        )
        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_blockchain_events_channel(
        token_address,
        channel12.partner_state.address,
    )
    assert len(event_list3) > len(event_list2)
    assert any(
        (
            event['event'] == ChannelEvent.CLOSED and
            is_same_address(
                event['args']['closing_participant'],
                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 + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS)

    state_changes = node1.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )

    assert must_contain_entry(state_changes, ContractReceiveChannelSettled, {
        'token_network_identifier': token_network_identifier,
        'channel_identifier': channel12.identifier,
    })
예제 #42
0
def test_lock_expiry(raiden_network, token_addresses, deposit):
    """Test lock expiry and removal."""
    alice_app, bob_app = raiden_network
    token_address = token_addresses[0]
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(alice_app),
        alice_app.raiden.default_registry.address,
        token_address,
    )

    hold_event_handler = HoldOffChainSecretRequest()
    wait_message_handler = WaitForMessage()
    bob_app.raiden.message_handler = wait_message_handler
    bob_app.raiden.raiden_event_handler = hold_event_handler

    token_network = views.get_token_network_by_identifier(
        views.state_from_app(alice_app),
        token_network_identifier,
    )

    channel_state = get_channelstate(alice_app, bob_app, token_network_identifier)
    channel_identifier = channel_state.identifier

    assert channel_identifier in token_network.partneraddresses_to_channelidentifiers[
        bob_app.raiden.address
    ]

    alice_to_bob_amount = 10
    identifier = 1
    target = bob_app.raiden.address
    transfer_1_secret = factories.make_secret(0)
    transfer_1_secrethash = sha3(transfer_1_secret)
    transfer_2_secret = factories.make_secret(1)
    transfer_2_secrethash = sha3(transfer_2_secret)

    hold_event_handler.hold_secretrequest_for(secrethash=transfer_1_secrethash)
    transfer1_received = wait_message_handler.wait_for_message(
        LockedTransfer,
        {'lock': {'secrethash': transfer_1_secrethash}},
    )
    transfer2_received = wait_message_handler.wait_for_message(
        LockedTransfer,
        {'lock': {'secrethash': transfer_2_secrethash}},
    )
    remove_expired_lock_received = wait_message_handler.wait_for_message(
        LockExpired,
        {'secrethash': transfer_1_secrethash},
    )

    alice_app.raiden.start_mediated_transfer_with_secret(
        token_network_identifier,
        alice_to_bob_amount,
        target,
        identifier,
        transfer_1_secret,
    )
    transfer1_received.wait()

    alice_bob_channel_state = get_channelstate(alice_app, bob_app, token_network_identifier)
    lock = channel.get_lock(alice_bob_channel_state.our_state, transfer_1_secrethash)

    # This is the current state of the protocol:
    #
    #    A -> B LockedTransfer
    #    B -> A SecretRequest
    #    - protocol didn't continue
    assert_synced_channel_state(
        token_network_identifier,
        alice_app, deposit, [lock],
        bob_app, deposit, [],
    )

    # Verify lock is registered in both channel states
    alice_channel_state = get_channelstate(alice_app, bob_app, token_network_identifier)
    assert transfer_1_secrethash in alice_channel_state.our_state.secrethashes_to_lockedlocks

    bob_channel_state = get_channelstate(bob_app, alice_app, token_network_identifier)
    assert transfer_1_secrethash in bob_channel_state.partner_state.secrethashes_to_lockedlocks

    alice_chain_state = views.state_from_raiden(alice_app.raiden)
    assert transfer_1_secrethash in alice_chain_state.payment_mapping.secrethashes_to_task

    remove_expired_lock_received.wait()

    alice_channel_state = get_channelstate(alice_app, bob_app, token_network_identifier)
    assert transfer_1_secrethash not in alice_channel_state.our_state.secrethashes_to_lockedlocks

    # Verify Bob received the message and processed the LockExpired message
    bob_channel_state = get_channelstate(bob_app, alice_app, token_network_identifier)
    assert transfer_1_secrethash not in bob_channel_state.partner_state.secrethashes_to_lockedlocks

    alice_chain_state = views.state_from_raiden(alice_app.raiden)
    assert transfer_1_secrethash not in alice_chain_state.payment_mapping.secrethashes_to_task

    # Make another transfer
    alice_to_bob_amount = 10
    identifier = 2

    hold_event_handler.hold_secretrequest_for(secrethash=transfer_2_secrethash)

    alice_app.raiden.start_mediated_transfer_with_secret(
        token_network_identifier,
        alice_to_bob_amount,
        target,
        identifier,
        transfer_2_secret,
    )
    transfer2_received.wait()

    # Make sure the other transfer still exists
    alice_chain_state = views.state_from_raiden(alice_app.raiden)
    assert transfer_2_secrethash in alice_chain_state.payment_mapping.secrethashes_to_task

    bob_channel_state = get_channelstate(bob_app, alice_app, token_network_identifier)
    assert transfer_2_secrethash in bob_channel_state.partner_state.secrethashes_to_lockedlocks
예제 #43
0
def test_settled_lock(token_addresses, raiden_network, deposit):
    """ Any transfer following a secret revealed must update the locksroot, so
    that an attacker cannot reuse a secret to double claim a lock."""
    app0, app1 = raiden_network
    registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]
    amount = 30
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(app0),
        app0.raiden.default_registry.address,
        token_address,
    )

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

    deposit0 = deposit
    deposit1 = deposit

    token_proxy = app0.raiden.chain.token(token_address)
    initial_balance0 = token_proxy.balance_of(address0)
    initial_balance1 = token_proxy.balance_of(address1)

    # Using a pending mediated transfer because this allows us to compute the
    # merkle proof
    identifier = 1
    secret = pending_mediated_transfer(
        raiden_network,
        token_network_identifier,
        amount,
        identifier,
    )
    secrethash = sha3(secret)

    # Compute the merkle proof for the pending transfer, and then unlock
    channelstate_0_1 = get_channelstate(app0, app1, token_network_identifier)
    lock = channel.get_lock(channelstate_0_1.our_state, secrethash)
    unlock_proof = channel.compute_proof_for_lock(
        channelstate_0_1.our_state,
        secret,
        lock,
    )
    claim_lock(raiden_network, identifier, token_network_identifier, secret)

    # Make a new transfer
    direct_transfer(app0, app1, token_network_identifier, amount, identifier=1)
    RaidenAPI(app1.raiden).channel_close(
        registry_address,
        token_address,
        app0.raiden.address,
    )

    # The direct transfer locksroot must not contain the unlocked lock, the
    # unlock must fail.
    netting_channel = app1.raiden.chain.netting_channel(
        channelstate_0_1.identifier)
    with pytest.raises(Exception):
        netting_channel.unlock(
            UnlockProofState(unlock_proof, lock.encoded, secret))

    waiting.wait_for_settle(
        app1.raiden,
        app1.raiden.default_registry.address,
        token_address,
        [channelstate_0_1.identifier],
        app1.raiden.alarm.wait_time,
    )

    expected_balance0 = initial_balance0 + deposit0 - amount * 2
    expected_balance1 = initial_balance1 + deposit1 + amount * 2

    assert token_proxy.balance_of(address0) == expected_balance0
    assert token_proxy.balance_of(address1) == expected_balance1
예제 #44
0
def test_locksroot_loading_during_channel_settle_handling(
        raiden_chain, deploy_client, token_addresses):
    app0, app1 = raiden_chain
    token_network_registry_address = app0.raiden.default_registry.address
    token_address = token_addresses[0]

    transfer(
        initiator_app=app0,
        target_app=app1,
        token_address=token_address,
        amount=10,
        identifier=1,
        transfer_state=TransferState.SECRET_NOT_REQUESTED,
    )
    transfer(
        initiator_app=app1,
        target_app=app0,
        token_address=token_address,
        amount=7,
        identifier=2,
        transfer_state=TransferState.SECRET_NOT_REQUESTED,
    )

    token_network_address = views.get_token_network_address_by_token_address(
        chain_state=views.state_from_raiden(app0.raiden),
        token_network_registry_address=token_network_registry_address,
        token_address=token_address,
    )
    channel_state = get_channelstate(
        app0=app0, app1=app1, token_network_address=token_network_address)

    channel = app0.raiden.proxy_manager.payment_channel(
        channel_state.canonical_identifier)
    balance_proof = channel_state.partner_state.balance_proof
    block_number = app0.raiden.rpc_client.block_number()

    closing_data = pack_signed_balance_proof(
        msg_type=MessageTypeId.BALANCE_PROOF,
        nonce=balance_proof.nonce,
        balance_hash=balance_proof.balance_hash,
        additional_hash=balance_proof.message_hash,
        canonical_identifier=balance_proof.canonical_identifier,
        partner_signature=balance_proof.signature,
    )
    closing_signature = app0.raiden.signer.sign(data=closing_data)

    channel.close(
        nonce=balance_proof.nonce,
        balance_hash=balance_proof.balance_hash,
        additional_hash=balance_proof.message_hash,
        non_closing_signature=balance_proof.signature,
        closing_signature=closing_signature,
        block_identifier=block_number,
    )

    close_block = app0.raiden.rpc_client.block_number()

    app0.stop()

    waiting.wait_for_settle(
        raiden=app1.raiden,
        token_network_registry_address=token_network_registry_address,
        token_address=token_address,
        channel_ids=[channel_state.canonical_identifier.channel_identifier],
        retry_timeout=1,
    )

    contract_proxy, _ = deploy_rpc_test_contract(deploy_client,
                                                 "RpcWithStorageTest")
    iterations = 1000

    def send_transaction():
        check_block = deploy_client.get_checking_block()
        startgas = contract_proxy.estimate_gas(check_block, "waste_storage",
                                               iterations)
        startgas = safe_gas_limit(startgas)
        transaction = contract_proxy.transact("waste_storage", startgas,
                                              iterations)
        return deploy_client.poll(transaction)

    for _ in range(10):
        send_transaction()

    # Wait until the target block has be prunned, it has to be larger than
    # pruning_history
    pruned_after_blocks = pruning_history * 1.5

    waiting.wait_for_block(raiden=app1.raiden,
                           block_number=close_block + pruned_after_blocks,
                           retry_timeout=1)

    channel = app0.raiden.proxy_manager.payment_channel(
        channel_state.canonical_identifier)

    # make sure the block was pruned
    with pytest.raises(ValueError):
        channel.detail(block_identifier=close_block)

    # This must not raise when the settle event is being raised and the
    # locksroot is being recover (#3856)
    app0.start()

    assert wait_for_state_change(
        raiden=app0.raiden,
        item_type=ContractReceiveChannelSettled,
        attributes={
            "canonical_identifier": channel_state.canonical_identifier
        },
        retry_timeout=1,
    )
def test_receive_lockedtransfer_invalidnonce(
        raiden_network,
        number_of_nodes,
        deposit,
        token_addresses,
        reveal_timeout,
        network_wait,
):

    app0, app1, app2 = raiden_network
    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,
    )
    channel0 = get_channelstate(app0, app1, token_network_identifier)

    amount = 10
    mediated_transfer(
        app0,
        app2,
        token_network_identifier,
        amount,
        timeout=network_wait * number_of_nodes,
    )

    amount = 10
    payment_identifier = 1
    repeated_nonce = 1
    expiration = reveal_timeout * 2
    mediated_transfer_message = LockedTransfer(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=random.randint(0, UINT64_MAX),
        payment_identifier=payment_identifier,
        nonce=repeated_nonce,
        token_network_address=token_network_identifier,
        token=token_address,
        channel_identifier=channel0.identifier,
        transferred_amount=amount,
        locked_amount=amount,
        recipient=app1.raiden.address,
        locksroot=UNIT_SECRETHASH,
        lock=Lock(amount, expiration, UNIT_SECRETHASH),
        target=app2.raiden.address,
        initiator=app0.raiden.address,
        fee=0,
    )

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

    with gevent.Timeout(network_wait):
        wait_assert(
            assert_synced_channel_state,
            token_network_identifier,
            app0, deposit - amount, [],
            app1, deposit + amount, [],
        )
예제 #46
0
def test_settle_is_automatically_called(raiden_network, token_addresses,
                                        deposit):
    """Settle is automatically called by one of the nodes."""
    app0, app1 = raiden_network
    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,
    )

    channel_identifier = get_channelstate(app0, app1,
                                          token_network_identifier).identifier

    # A ChannelClose event will be generated, this will be polled by both apps
    # and each must start a task for calling settle
    RaidenAPI(app1.raiden).channel_close(
        registry_address,
        token_address,
        app0.raiden.address,
    )

    waiting.wait_for_settle(
        app0.raiden,
        registry_address,
        token_address,
        [channel_identifier],
        app0.raiden.alarm.wait_time,
    )

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

    state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )

    channel_state = get_channelstate(app0, app1, token_network_identifier)
    assert channel_state.close_transaction.finished_block_number
    assert channel_state.settle_transaction.finished_block_number

    assert must_contain_entry(
        state_changes, ContractReceiveChannelClosed, {
            'token_network_identifier':
            token_network_identifier,
            'channel_identifier':
            channel_identifier,
            'closing_address':
            app1.raiden.address,
            'closed_block_number':
            channel_state.close_transaction.finished_block_number,
        })

    assert must_contain_entry(
        state_changes, ContractReceiveChannelSettled, {
            'token_network_identifier':
            token_network_identifier,
            'channel_identifier':
            channel_identifier,
            'settle_block_number':
            channel_state.settle_transaction.finished_block_number,
        })
예제 #47
0
def test_secret_revealed_on_chain(
        raiden_chain,
        deposit,
        settle_timeout,
        token_addresses,
        retry_interval,
):
    """ A node must reveal the secret on-chain if it's known and the channel is closed. """
    app0, app1, app2 = raiden_chain
    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
    target = app2.raiden.address
    secret = sha3(target)
    secrethash = sha3(secret)

    # Reveal the secret, but do not unlock it off-chain
    app1_hold_event_handler = HoldOffChainSecretRequest()
    app1.raiden.raiden_event_handler = app1_hold_event_handler
    app1_hold_event_handler.hold_unlock_for(secrethash=secrethash)

    app0.raiden.start_mediated_transfer_with_secret(
        token_network_identifier,
        amount,
        target,
        identifier,
        secret,
    )

    with gevent.Timeout(10):
        wait_for_state_change(
            app2.raiden,
            ReceiveSecretReveal,
            {'secrethash': secrethash},
            retry_interval,
        )

    channel_state2_1 = get_channelstate(app2, app1, token_network_identifier)
    pending_lock = channel_state2_1.partner_state.secrethashes_to_unlockedlocks.get(secrethash)
    msg = "The lock must be registered in unlocked locks since the secret is known"
    assert pending_lock is not None, msg

    # The channels are out-of-sync. app1 has sent the unlock, however we are
    # intercepting it and app2 has not received the updated balance proof

    # Close the channel. This must register the secret on chain
    channel_close_event = ContractSendChannelClose(
        channel_identifier=channel_state2_1.identifier,
        token_address=channel_state2_1.token_address,
        token_network_identifier=token_network_identifier,
        balance_proof=channel_state2_1.partner_state.balance_proof,
    )
    app2.raiden.raiden_event_handler.on_raiden_event(app2.raiden, channel_close_event)

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

    # TODO:
    # - assert on the transferred amounts on-chain (for settle and unlock)

    # The channel app0-app1 should continue with the protocol off-chain, once
    # the secret is released on-chain by app2
    assert_synced_channel_state(
        token_network_identifier,
        app0, deposit - amount, [],
        app1, deposit + amount, [],
    )

    with gevent.Timeout(10):
        wait_for_state_change(
            app2.raiden,
            ContractReceiveSecretReveal,
            {'secrethash': secrethash},
            retry_interval,
        )
예제 #48
0
def test_regression_multiple_revealsecret(
        raiden_network: List[App],
        token_addresses: List[TokenAddress]) -> None:
    """ Multiple RevealSecret messages arriving at the same time must be
    handled properly.

    Unlock handling followed these steps:

        The Unlock message arrives
        The secret is registered
        The channel is updated and the correspoding lock is removed
        * A balance proof for the new channel state is created and sent to the
          payer
        The channel is unregistered for the given secrethash

    The step marked with an asterisk above introduced a context-switch. This
    allowed a second Reveal Unlock message to be handled before the channel was
    unregistered. And because the channel was already updated an exception was raised
    for an unknown secret.
    """
    app0, app1 = raiden_network
    token = token_addresses[0]
    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_app(app0), app0.raiden.default_registry.address,
        token)
    assert token_network_address
    channelstate_0_1 = get_channelstate(app0, app1, token_network_address)

    payment_identifier = PaymentID(1)
    secret, secrethash = make_secret_with_hash()
    expiration = BlockExpiration(app0.raiden.get_block_number() + 100)
    lock_amount = PaymentWithFeeAmount(10)
    lock = Lock(amount=lock_amount,
                expiration=expiration,
                secrethash=secrethash)

    nonce = Nonce(1)
    transferred_amount = TokenAmount(0)
    mediated_transfer = LockedTransfer(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=make_message_identifier(),
        payment_identifier=payment_identifier,
        nonce=nonce,
        token_network_address=token_network_address,
        token=token,
        channel_identifier=channelstate_0_1.identifier,
        transferred_amount=transferred_amount,
        locked_amount=TokenAmount(lock_amount),
        recipient=app1.raiden.address,
        locksroot=Locksroot(lock.lockhash),
        lock=lock,
        target=TargetAddress(app1.raiden.address),
        initiator=InitiatorAddress(app0.raiden.address),
        signature=EMPTY_SIGNATURE,
        metadata=Metadata(routes=[
            RouteMetadata(route=[app0.raiden.address, app1.raiden.address])
        ]),
    )
    app0.raiden.sign(mediated_transfer)
    app1.raiden.on_messages([mediated_transfer])

    reveal_secret = RevealSecret(message_identifier=make_message_identifier(),
                                 secret=secret,
                                 signature=EMPTY_SIGNATURE)
    app0.raiden.sign(reveal_secret)

    token_network_address = channelstate_0_1.token_network_address
    unlock = Unlock(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=make_message_identifier(),
        payment_identifier=payment_identifier,
        nonce=Nonce(mediated_transfer.nonce + 1),
        token_network_address=token_network_address,
        channel_identifier=channelstate_0_1.identifier,
        transferred_amount=TokenAmount(lock_amount),
        locked_amount=TokenAmount(0),
        locksroot=LOCKSROOT_OF_NO_LOCKS,
        secret=secret,
        signature=EMPTY_SIGNATURE,
    )
    app0.raiden.sign(unlock)

    messages = [unlock, reveal_secret]
    receive_method = app1.raiden.on_messages
    wait = set(
        gevent.spawn_later(0.1, receive_method, [data]) for data in messages)

    gevent.joinall(wait)
예제 #49
0
def test_secret_revealed_on_chain(
    raiden_chain: List[RaidenService],
    deposit,
    settle_timeout,
    token_addresses,
    retry_interval_initial,
):
    """ A node must reveal the secret on-chain if it's known and the channel is closed. """
    app0, app1, app2 = raiden_chain
    token_address = token_addresses[0]
    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_raiden(app0), app0.default_registry.address,
        token_address)
    assert token_network_address

    amount = PaymentAmount(10)
    identifier = PaymentID(1)
    target = TargetAddress(app2.address)
    secret, secrethash = factories.make_secret_with_hash()

    # Reveal the secret, but do not unlock it off-chain
    app1_hold_event_handler = app1.raiden_event_handler

    msg = "test apps must have HoldRaidenEventHandler set"
    assert isinstance(app1_hold_event_handler, HoldRaidenEventHandler), msg

    app1_hold_event_handler.hold_unlock_for(secrethash=secrethash)

    app0.mediated_transfer_async(
        token_network_address=token_network_address,
        amount=amount,
        target=target,
        identifier=identifier,
        secret=secret,
        route_states=[
            create_route_state_for_route(
                apps=raiden_chain,
                token_address=token_address,
                fee_estimate=FeeAmount(
                    round(INTERNAL_ROUTING_DEFAULT_FEE_PERC * amount)),
            )
        ],
    )

    with watch_for_unlock_failures(*raiden_chain), block_offset_timeout(app0):
        wait_for_state_change(app2, ReceiveSecretReveal,
                              {"secrethash": secrethash},
                              retry_interval_initial)

    channel_state2_1 = get_channelstate(app2, app1, token_network_address)
    pending_lock = channel_state2_1.partner_state.secrethashes_to_unlockedlocks.get(
        secrethash)
    msg = "The lock must be registered in unlocked locks since the secret is known"
    assert pending_lock is not None, msg

    # The channels are out-of-sync. app1 has sent the unlock, however we are
    # intercepting it and app2 has not received the updated balance proof

    # Close the channel. This must register the secret on chain
    balance_proof = channel_state2_1.partner_state.balance_proof
    assert isinstance(balance_proof, BalanceProofSignedState)
    channel_close_event = ContractSendChannelClose(
        canonical_identifier=channel_state2_1.canonical_identifier,
        balance_proof=balance_proof,
        triggered_by_block_hash=app0.rpc_client.blockhash_from_blocknumber(
            BLOCK_ID_LATEST),
    )

    assert app2.wal, "test apps must be started by the fixture."
    current_state = views.state_from_raiden(app2)

    app2.raiden_event_handler.on_raiden_events(raiden=app2,
                                               chain_state=current_state,
                                               events=[channel_close_event])

    settle_expiration = (app0.rpc_client.block_number() + settle_timeout +
                         DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS)
    app0.proxy_manager.client.wait_until_block(
        target_block_number=settle_expiration)

    # TODO:
    # - assert on the transferred amounts on-chain (for settle and unlock)

    # The channel app0-app1 should continue with the protocol off-chain, once
    # the secret is released on-chain by app2
    assert_synced_channel_state(token_network_address, app0, deposit - amount,
                                [], app1, deposit + amount, [])

    with watch_for_unlock_failures(*raiden_chain), gevent.Timeout(10):
        wait_for_state_change(
            app2,
            ContractReceiveSecretReveal,
            {"secrethash": secrethash},
            retry_interval_initial,
        )
예제 #50
0
def test_clear_closed_queue(raiden_network: List[RaidenService],
                            token_addresses, network_wait):
    """ Closing a channel clears the respective message queue. """
    app0, app1 = raiden_network

    hold_event_handler = app1.raiden_event_handler
    assert isinstance(hold_event_handler, HoldRaidenEventHandler)

    registry_address = app0.default_registry.address
    token_address = token_addresses[0]
    chain_state0 = views.state_from_raiden(app0)
    token_network_address = views.get_token_network_address_by_token_address(
        chain_state0, app0.default_registry.address, token_address)
    assert token_network_address
    token_network = views.get_token_network_by_address(chain_state0,
                                                       token_network_address)
    assert token_network

    channel_identifier = get_channelstate(app0, app1,
                                          token_network_address).identifier

    assert channel_identifier in token_network.partneraddresses_to_channelidentifiers[
        app1.address]

    target = app1.address
    secret = Secret(keccak(target))
    secrethash = sha256_secrethash(secret)
    hold_event_handler.hold_secretrequest_for(secrethash=secrethash)

    # make an unconfirmed transfer to ensure the nodes have communicated
    amount = PaymentAmount(10)
    payment_identifier = PaymentID(1337)
    app0.mediated_transfer_async(
        token_network_address=token_network_address,
        amount=amount,
        target=TargetAddress(target),
        identifier=payment_identifier,
        secret=secret,
    )

    app1.transport.stop()
    app1.transport.greenlet.get()

    # make sure to wait until the queue is created
    def has_initiator_events():
        assert app0.wal, "raiden server must have been started"
        initiator_events = app0.wal.storage.get_events()
        return search_for_item(initiator_events, SendLockedTransfer, {})

    assert wait_until(has_initiator_events, network_wait)

    # assert the specific queue is present
    chain_state0 = views.state_from_raiden(app0)
    queues0 = views.get_all_messagequeues(chain_state=chain_state0)
    assert [
        (queue_id, queue) for queue_id, queue in queues0.items()
        if queue_id.recipient == app1.address and queue_id.
        canonical_identifier.channel_identifier == channel_identifier and queue
    ]

    # A ChannelClose event will be generated, this will be polled by both apps
    RaidenAPI(app0).channel_close(registry_address, token_address,
                                  app1.address)

    with block_offset_timeout(app0, "Could not get close event"):
        waiting.wait_for_close(
            app0,
            registry_address,
            token_address,
            [channel_identifier],
            app0.alarm.sleep_time,
        )

    # assert all queues with this partner are gone or empty
    chain_state0 = views.state_from_raiden(app0)
    queues0 = views.get_all_messagequeues(chain_state=chain_state0)
    assert not [(queue_id, queue) for queue_id, queue in queues0.items()
                if queue_id.recipient == app1.address and queue]

    chain_state1 = views.state_from_raiden(app1)
    queues1 = views.get_all_messagequeues(chain_state=chain_state1)
    assert not [(queue_id, queue) for queue_id, queue in queues1.items()
                if queue_id.recipient == app0.address and queue]
예제 #51
0
def test_batch_unlock(raiden_network, token_addresses, secret_registry_address, deposit):
    """Batch unlock can be called after the channel is settled."""
    alice_app, bob_app = raiden_network
    registry_address = alice_app.raiden.default_registry.address
    token_address = token_addresses[0]
    token_proxy = alice_app.raiden.chain.token(token_address)
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        views.state_from_app(alice_app),
        alice_app.raiden.default_registry.address,
        token_address,
    )

    hold_event_handler = HoldOffChainSecretRequest()
    bob_app.raiden.raiden_event_handler = hold_event_handler

    # Take a snapshot early on
    alice_app.raiden.wal.snapshot()

    token_network = views.get_token_network_by_identifier(
        views.state_from_app(alice_app),
        token_network_identifier,
    )

    channel_identifier = get_channelstate(alice_app, bob_app, token_network_identifier).identifier

    assert channel_identifier in token_network.partneraddresses_to_channelidentifiers[
        bob_app.raiden.address
    ]

    alice_initial_balance = token_proxy.balance_of(alice_app.raiden.address)
    bob_initial_balance = token_proxy.balance_of(bob_app.raiden.address)

    # Take snapshot before transfer
    alice_app.raiden.wal.snapshot()

    alice_to_bob_amount = 10
    identifier = 1
    target = bob_app.raiden.address
    secret = sha3(target)
    secrethash = sha3(secret)

    hold_event_handler.hold_secretrequest_for(secrethash=secrethash)

    alice_app.raiden.start_mediated_transfer_with_secret(
        token_network_identifier,
        alice_to_bob_amount,
        target,
        identifier,
        secret,
    )

    gevent.sleep(1)  # wait for the messages to be exchanged

    alice_bob_channel_state = get_channelstate(alice_app, bob_app, token_network_identifier)
    lock = channel.get_lock(alice_bob_channel_state.our_state, secrethash)

    # This is the current state of the protocol:
    #
    #    A -> B LockedTransfer
    #    B -> A SecretRequest
    #    - protocol didn't continue
    assert_synced_channel_state(
        token_network_identifier,
        alice_app, deposit, [lock],
        bob_app, deposit, [],
    )

    # Take a snapshot early on
    alice_app.raiden.wal.snapshot()

    our_balance_proof = alice_bob_channel_state.our_state.balance_proof

    # Test WAL restore to return the latest channel state
    restored_channel_state = channel_state_until_state_change(
        raiden=alice_app.raiden,
        payment_network_identifier=alice_app.raiden.default_registry.address,
        token_address=token_address,
        channel_identifier=alice_bob_channel_state.identifier,
        state_change_identifier='latest',
    )

    our_restored_balance_proof = restored_channel_state.our_state.balance_proof
    assert our_balance_proof == our_restored_balance_proof

    # A ChannelClose event will be generated, this will be polled by both apps
    # and each must start a task for calling settle
    RaidenAPI(bob_app.raiden).channel_close(
        registry_address,
        token_address,
        alice_app.raiden.address,
    )

    secret_registry_proxy = alice_app.raiden.chain.secret_registry(
        secret_registry_address,
    )
    secret_registry_proxy.register_secret(secret)

    assert lock, 'the lock must still be part of the node state'
    msg = 'the secret must be registered before the lock expires'
    assert lock.expiration > alice_app.raiden.get_block_number(), msg
    assert lock.secrethash == sha3(secret)

    waiting.wait_for_settle(
        alice_app.raiden,
        registry_address,
        token_address,
        [alice_bob_channel_state.identifier],
        alice_app.raiden.alarm.sleep_time,
    )

    token_network = views.get_token_network_by_identifier(
        views.state_from_app(bob_app),
        token_network_identifier,
    )

    assert channel_identifier in token_network.partneraddresses_to_channelidentifiers[
        alice_app.raiden.address
    ]

    # wait for the node to call batch unlock
    with gevent.Timeout(10):
        wait_for_batch_unlock(
            bob_app,
            token_network_identifier,
            alice_bob_channel_state.partner_state.address,
            alice_bob_channel_state.our_state.address,
        )

    token_network = views.get_token_network_by_identifier(
        views.state_from_app(bob_app),
        token_network_identifier,
    )

    assert channel_identifier not in token_network.partneraddresses_to_channelidentifiers[
        alice_app.raiden.address
    ]

    alice_new_balance = alice_initial_balance + deposit - alice_to_bob_amount
    bob_new_balance = bob_initial_balance + deposit + alice_to_bob_amount

    assert token_proxy.balance_of(alice_app.raiden.address) == alice_new_balance
    assert token_proxy.balance_of(bob_app.raiden.address) == bob_new_balance
예제 #52
0
def test_invalid_close(
    raiden_network,
    number_of_nodes,
    deposit,
    token_addresses,
    network_wait,
):
    app0, app1 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    registry_address = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state=chain_state,
        payment_network_id=payment_network_id,
        token_address=token_address,
    )
    channel_identifier = get_channelstate(app0, app1,
                                          token_network_identifier).identifier

    # make a transfer from app0 to app1 so that app1 is supposed to have a non empty balance hash
    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=1,
        timeout=network_wait * number_of_nodes,
    )
    # stop app1 - the test uses token_network_contract now
    app1.stop()
    token_network_contract = TokenNetwork(
        jsonrpc_client=app1.raiden.chain.client,
        token_network_address=token_network_identifier,
        contract_manager=app1.raiden.contract_manager,
    )

    # app1 closes the channel with an empty hash instead of the expected hash
    # of the transferred amount from app0
    token_network_contract.close(
        channel_identifier=channel_identifier,
        partner=app0.raiden.address,
        balance_hash=EMPTY_HASH,
        nonce=0,
        additional_hash=EMPTY_HASH,
        signature=EMPTY_SIGNATURE,
    )
    waiting.wait_for_close(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )
    waiting.wait_for_settle(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )
    state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )
    assert must_contain_entry(
        state_changes, ContractReceiveChannelSettled, {
            'token_network_identifier': token_network_identifier,
            'channel_identifier': channel_identifier,
        })
예제 #53
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,
    )

    hold_event_handler = HoldOffChainSecretRequest()
    app2.raiden.raiden_event_handler = hold_event_handler

    # the attacker owns app0 and app2 and creates a transfer through app1
    identifier = 1
    target = app2.raiden.address
    secret = sha3(target)
    secrethash = sha3(secret)

    hold_event_handler.hold_secretrequest_for(secrethash=secrethash)

    app0.raiden.start_mediated_transfer_with_secret(
        token_network_identifier,
        amount,
        target,
        identifier,
        secret,
    )

    gevent.sleep(1)  # wait for the messages to be exchanged

    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
예제 #54
0
def test_invalid_update_transfer(
    raiden_network,
    number_of_nodes,
    deposit,
    token_addresses,
    network_wait,
    chain_id,
):
    app0, app1 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    registry_address = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state=chain_state,
        payment_network_id=payment_network_id,
        token_address=token_address,
    )
    channel_identifier = get_channelstate(app0, app1,
                                          token_network_identifier).identifier

    # make a transfer
    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=1,
        timeout=network_wait * number_of_nodes,
    )
    # stop app1 - the test uses token_network_contract now
    app1.stop()
    # close the channel
    RaidenAPI(app0.raiden).channel_close(
        registry_address=registry_address,
        token_address=token_address,
        partner_address=app1.raiden.address,
    )
    waiting.wait_for_close(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )

    # app1 won't update the channel

    # app0 waits for settle
    waiting.wait_for_settle(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )
    state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )
    assert must_contain_entry(
        state_changes, ContractReceiveChannelSettled, {
            'token_network_identifier': token_network_identifier,
            'channel_identifier': channel_identifier,
        })
예제 #55
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

    # 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(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(
        token_address,
        channel12.partner_state.address,
        channel12.open_transaction.finished_block_number,
    )
    assert any(
        (
            event['event'] == EVENT_CHANNEL_OPENED and
            is_same_address(
                event['args']['participant1'],
                to_normalized_address(api1.address),
            ) and
            is_same_address(
                event['args']['participant2'],
                to_normalized_address(api2.address),
            )
        )
        for event in event_list1
    )

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

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

    # let's make sure it's idempotent
    api1.set_total_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(
        token_address,
        channel12.partner_state.address,
        channel12.open_transaction.finished_block_number,
    )
    assert any(
        (
            event['event'] == EVENT_CHANNEL_DEPOSIT and
            is_same_address(
                event['args']['participant'],
                to_normalized_address(api1.address),
            ) and
            event['args']['total_deposit'] == deposit
        )
        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(
        token_address,
        channel12.partner_state.address,
        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']['closing_participant'],
                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
예제 #56
0
def test_node_can_settle_if_partner_does_not_call_update_transfer(
        raiden_network,
        number_of_nodes,
        deposit,
        token_addresses,
        network_wait,
        chain_id,
):
    """ A node must be able to settle a channel, even if the partner did not
    call update transfer.

    This test will:
    - Make a transfer from app0 to app1, to make sure there are balance
    proofs available
    - Stop app1, to make sure update is not called.
    - Use app0 to close the channel.
    - Assert that app0 can settle the closed channel, even though app1 didn't
    use the latest balance proof
    """

    app0, app1 = raiden_network
    token_address = token_addresses[0]
    chain_state = views.state_from_app(app0)
    payment_network_id = app0.raiden.default_registry.address
    registry_address = app0.raiden.default_registry.address
    token_network_identifier = views.get_token_network_identifier_by_token_address(
        chain_state=chain_state,
        payment_network_id=payment_network_id,
        token_address=token_address,
    )
    channel_identifier = get_channelstate(app0, app1, token_network_identifier).identifier

    mediated_transfer(
        initiator_app=app0,
        target_app=app1,
        token_network_identifier=token_network_identifier,
        amount=1,
        timeout=network_wait * number_of_nodes,
    )
    # stop app1 - the test uses token_network_contract now
    app1.stop()
    RaidenAPI(app0.raiden).channel_close(
        registry_address=registry_address,
        token_address=token_address,
        partner_address=app1.raiden.address,
    )
    waiting.wait_for_close(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )

    # app1 won't update the channel

    waiting.wait_for_settle(
        raiden=app0.raiden,
        payment_network_id=registry_address,
        token_address=token_address,
        channel_ids=[channel_identifier],
        retry_timeout=app0.raiden.alarm.sleep_time,
    )
    state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier(
        from_identifier=0,
        to_identifier='latest',
    )
    assert must_contain_entry(state_changes, ContractReceiveChannelSettled, {
        'token_network_identifier': token_network_identifier,
        'channel_identifier': channel_identifier,
    })