Exemplo n.º 1
0
def events_for_unlock_if_closed(
    channelidentifiers_to_channels,
    transfers_pair,
    secret,
    secrethash,
):
    """ Unlock on chain if the payer channel is closed and the secret is known.
    If a channel is closed because of another task a balance proof will not be
    received, so there is no reason to wait for the unsafe region before
    calling close.
    This may break the reverse reveal order:
        Path: A -- B -- C -- B -- D
        B learned the secret from D and has revealed to C.
        C has not confirmed yet.
        channel(A, B).closed is True.
        B will unlock on channel(A, B) before C's confirmation.
        A may learn the secret faster than other nodes.
    """
    events = list()
    pending_transfers_pairs = get_pending_transfer_pairs(transfers_pair)

    for pair in pending_transfers_pairs:
        payer_channel = get_payer_channel(channelidentifiers_to_channels, pair)

        payer_channel_open = channel.get_status(
            payer_channel) == CHANNEL_STATE_OPENED

        # The unlock is done by the channel
        if not payer_channel_open:
            pair.payer_state = 'payer_waiting_unlock'

            partner_state = payer_channel.partner_state
            lock = channel.get_lock(partner_state, secrethash)
            unlock_proof = channel.compute_proof_for_lock(
                partner_state,
                secret,
                lock,
            )
            unlock = ContractSendChannelBatchUnlock(
                payer_channel.token_network_identifier,
                payer_channel.identifier,
                [unlock_proof],
            )
            events.append(unlock)

    return events
Exemplo n.º 2
0
def events_for_unlock_if_closed(
        channelidentifiers_to_channels,
        transfers_pair,
        secret,
        secrethash):
    """ Unlock on chain if the payer channel is closed and the secret is known.
    If a channel is closed because of another task a balance proof will not be
    received, so there is no reason to wait for the unsafe region before
    calling close.
    This may break the reverse reveal order:
        Path: A -- B -- C -- B -- D
        B learned the secret from D and has revealed to C.
        C has not confirmed yet.
        channel(A, B).closed is True.
        B will unlock on channel(A, B) before C's confirmation.
        A may learn the secret faster than other nodes.
    """
    events = list()
    pending_transfers_pairs = get_pending_transfer_pairs(transfers_pair)

    for pair in pending_transfers_pairs:
        payer_channel = get_payer_channel(channelidentifiers_to_channels, pair)

        payer_channel_open = channel.get_status(payer_channel) == CHANNEL_STATE_OPENED

        # The unlock is done by the channel
        if not payer_channel_open:
            pair.payer_state = 'payer_waiting_unlock'

            partner_state = payer_channel.partner_state
            lock = channel.get_lock(partner_state, secrethash)
            unlock_proof = channel.compute_proof_for_lock(
                partner_state,
                secret,
                lock,
            )
            unlock = ContractSendChannelBatchUnlock(
                payer_channel.token_network_identifier,
                payer_channel.identifier,
                [unlock_proof],
            )
            events.append(unlock)

    return events
Exemplo n.º 3
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,
    })
Exemplo n.º 4
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
Exemplo n.º 5
0
def test_withdraw(
        tester_registry_address,
        deposit,
        settle_timeout,
        reveal_timeout,
        tester_channels,
        tester_chain,
        tester_token,
):

    pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0]
    pseudo_random_generator = random.Random()

    address0 = privatekey_to_address(pkey0)
    address1 = privatekey_to_address(pkey1)

    initial_balance0 = tester_token.balanceOf(address0, sender=pkey0)
    initial_balance1 = tester_token.balanceOf(address1, sender=pkey0)

    lock_amount = 31
    lock_expiration = tester_chain.block.number + reveal_timeout + 5
    secret = b'secretsecretsecretsecretsecretse'
    secrethash = sha3(secret)
    new_block = Block(tester_chain.block.number)
    channel.state_transition(
        channel0,
        new_block,
        pseudo_random_generator,
        new_block.block_number,
    )
    channel.state_transition(
        channel1,
        new_block,
        pseudo_random_generator,
        new_block.block_number,
    )
    lock0 = Lock(lock_amount, lock_expiration, secrethash)

    mediated0 = make_mediated_transfer(
        tester_registry_address,
        channel0,
        channel1,
        address0,
        address1,
        lock0,
        pkey0,
        secret,
    )

    # withdraw the pending transfer sent to us by our partner
    lock_state = lockstate_from_lock(mediated0.lock)
    proof = channel.compute_proof_for_lock(
        channel1.partner_state,
        secret,
        lock_state,
    )

    mediated0_hash = sha3(mediated0.packed().data[:-65])
    nettingchannel.close(
        mediated0.nonce,
        mediated0.transferred_amount,
        mediated0.locksroot,
        mediated0_hash,
        mediated0.signature,
        sender=pkey1,
    )

    tester_chain.mine(number_of_blocks=1)

    nettingchannel.withdraw(
        proof.lock_encoded,
        b''.join(proof.merkle_proof),
        proof.secret,
        sender=pkey1,
    )

    tester_chain.mine(number_of_blocks=settle_timeout + 1)
    nettingchannel.settle(sender=pkey0)

    balance0 = initial_balance0 + deposit - lock0.amount
    balance1 = initial_balance1 + deposit + lock0.amount
    assert tester_token.balanceOf(address0, sender=pkey0) == balance0
    assert tester_token.balanceOf(address1, sender=pkey0) == balance1
    assert tester_token.balanceOf(nettingchannel.address, sender=pkey0) == 0
Exemplo n.º 6
0
def test_withdraw_both_participants(
        tester_registry_address,
        deposit,
        settle_timeout,
        reveal_timeout,
        tester_channels,
        tester_chain,
        tester_token,
):

    pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0]
    pseudo_random_generator = random.Random()

    address0 = privatekey_to_address(pkey0)
    address1 = privatekey_to_address(pkey1)

    initial_balance0 = tester_token.balanceOf(address0, sender=pkey0)
    initial_balance1 = tester_token.balanceOf(address1, sender=pkey0)

    secret = b'secretsecretsecretsecretsecretse'
    secrethash = sha3(secret)

    lock_amount = 31
    lock01_expiration = tester_chain.block.number + settle_timeout - 1 * reveal_timeout
    lock10_expiration = tester_chain.block.number + settle_timeout - 2 * reveal_timeout

    new_block = Block(tester_chain.block.number)
    channel.state_transition(
        channel0,
        new_block,
        pseudo_random_generator,
        new_block.block_number,
    )
    channel.state_transition(
        channel1,
        new_block,
        pseudo_random_generator,
        new_block.block_number,
    )

    # using the same secrethash and amount is intentional
    lock01 = Lock(lock_amount, lock01_expiration, secrethash)
    lock10 = Lock(lock_amount, lock10_expiration, secrethash)

    mediated01 = make_mediated_transfer(
        tester_registry_address,
        channel0,
        channel1,
        address0,
        address1,
        lock01,
        pkey0,
        secret,
    )

    mediated10 = make_mediated_transfer(
        tester_registry_address,
        channel1,
        channel0,
        address1,
        address0,
        lock10,
        pkey1,
        secret,
    )

    mediated01_hash = sha3(mediated01.packed().data[:-65])
    nettingchannel.close(
        mediated01.nonce,
        mediated01.transferred_amount,
        mediated01.locksroot,
        mediated01_hash,
        mediated01.signature,
        sender=pkey1,
    )
    tester_chain.mine(number_of_blocks=1)

    mediated10_hash = sha3(mediated10.packed().data[:-65])
    nettingchannel.updateTransfer(
        mediated10.nonce,
        mediated10.transferred_amount,
        mediated10.locksroot,
        mediated10_hash,
        mediated10.signature,
        sender=pkey0,
    )
    tester_chain.mine(number_of_blocks=1)

    lock_state01 = lockstate_from_lock(mediated01.lock)
    proof01 = channel.compute_proof_for_lock(
        channel1.partner_state,
        secret,
        lock_state01,
    )
    nettingchannel.withdraw(
        proof01.lock_encoded,
        b''.join(proof01.merkle_proof),
        proof01.secret,
        sender=pkey1,
    )

    lock_state10 = lockstate_from_lock(mediated10.lock)
    proof10 = channel.compute_proof_for_lock(
        channel0.partner_state,
        secret,
        lock_state10,
    )
    nettingchannel.withdraw(
        proof10.lock_encoded,
        b''.join(proof10.merkle_proof),
        proof10.secret,
        sender=pkey0,
    )

    tester_chain.mine(number_of_blocks=settle_timeout + 1)
    nettingchannel.settle(sender=pkey0)

    balance0 = initial_balance0 + deposit - lock01.amount + lock10.amount
    balance1 = initial_balance1 + deposit + lock01.amount - lock10.amount
    assert tester_token.balanceOf(address0, sender=pkey0) == balance0
    assert tester_token.balanceOf(address1, sender=pkey0) == balance1
    assert tester_token.balanceOf(nettingchannel.address, sender=pkey0) == 0