Beispiel #1
0
    def get(
        participant1: HexAddress,
        locked_amount1: int,
        locksroot1: bytes,
        participant2: HexAddress,
        locked_amount2: int,
        locksroot2: bytes,
        settle_timeout: int = TEST_SETTLE_TIMEOUT_MIN,
    ) -> int:
        participant1_values = ChannelValues(
            transferred=5,
            locked_amounts=LockedAmounts(claimable_locked=locked_amount1),
            locksroot=locksroot1,
        )
        participant2_values = ChannelValues(
            transferred=40,
            locked_amounts=LockedAmounts(claimable_locked=locked_amount2),
            locksroot=locksroot2,
        )

        participant1_values.deposit = (
            participant1_values.locked_amounts.locked +
            participant1_values.transferred - 5)
        participant2_values.deposit = (
            participant2_values.locked_amounts.locked +
            participant2_values.transferred + 5)

        channel_identifier = create_channel_and_deposit(
            participant1,
            participant2,
            participant1_values.deposit,
            participant2_values.deposit,
            settle_timeout,
        )

        close_and_update_channel(
            channel_identifier,
            participant1,
            participant1_values,
            participant2,
            participant2_values,
        )

        mine_blocks(web3, settle_timeout)

        call_settle(
            token_network,
            channel_identifier,
            participant1,
            participant1_values,
            participant2,
            participant2_values,
        )

        return channel_identifier
Beispiel #2
0
def test_channel_unlock_with_a_large_expiration(
    web3,
    custom_token,
    token_network,
    create_channel,
    channel_deposit,
    get_accounts,
    close_and_update_channel,
    reveal_secrets,
):
    """ unlock() should still work after a delayed settleChannel() call """
    (A, B) = get_accounts(2)
    settle_timeout = 8

    values_A = ChannelValues(deposit=20, transferred=5)
    values_B = ChannelValues(deposit=30, transferred=40)

    # Create channel and deposit
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, A, values_A.deposit, B)
    channel_deposit(channel_identifier, B, values_B.deposit, A)

    # Mock pending transfers data with large expiration date
    pending_transfers_tree = get_pending_transfers_tree(
        web3, [1, 3, 5], [2, 4], settle_timeout + 100)
    values_B.locksroot = pending_transfers_tree.merkle_root
    values_B.locked_amounts = LockedAmounts(
        claimable_locked=get_locked_amount(pending_transfers_tree.transfers))

    # Reveal secrets before settlement window ends
    reveal_secrets(A, pending_transfers_tree.unlockable)

    close_and_update_channel(channel_identifier, A, values_A, B, values_B)

    # Settle channel after a "long" time
    web3.testing.mine(settle_timeout + 50)

    call_settle(token_network, channel_identifier, A, values_A, B, values_B)

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # Unlock the tokens must still work
    token_network.functions.unlock(
        channel_identifier, A, B,
        pending_transfers_tree.packed_transfers).call_and_transact()

    balance_A = custom_token.functions.balanceOf(A).call()
    balance_B = custom_token.functions.balanceOf(B).call()
    balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()
    assert balance_A == pre_balance_A + 9
    assert balance_B == pre_balance_B + 6
    assert balance_contract == pre_balance_contract - values_B.locked_amounts.locked
Beispiel #3
0
def test_channel_unlock_unregistered_locks(
    web3,
    token_network,
    get_accounts,
    create_channel_and_deposit,
    withdraw_channel,
    close_and_update_channel,
    custom_token,
):
    """ unlock() should refund tokens locked by secrets not registered before settlement """
    (A, B) = get_accounts(2)
    settle_timeout = TEST_SETTLE_TIMEOUT_MIN

    pending_transfers_tree = get_pending_transfers_tree(
        web3, [1, 3, 5], [2, 4], settle_timeout)
    locked_A = pending_transfers_tree.locked_amount
    (vals_A, vals_B) = (
        ChannelValues(
            deposit=35,
            withdrawn=10,
            transferred=0,
            locked_amounts=LockedAmounts(claimable_locked=locked_A),
        ),
        ChannelValues(deposit=40, withdrawn=10, transferred=20),
    )

    vals_A.locksroot = "0x" + get_merkle_root(
        pending_transfers_tree.merkle_tree).hex()
    vals_B.locksroot = fake_bytes(32, "03")
    channel_identifier = create_channel_and_deposit(A, B, vals_A.deposit,
                                                    vals_B.deposit)
    withdraw_channel(channel_identifier, A, vals_A.withdrawn, B)
    withdraw_channel(channel_identifier, B, vals_B.withdrawn, A)

    close_and_update_channel(channel_identifier, A, vals_A, B, vals_B)

    # Secret hasn't been registered before settlement timeout
    web3.testing.mine(TEST_SETTLE_TIMEOUT_MIN + 1)
    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)

    # Someone unlocks A's pending transfers - all tokens should be refunded
    token_network.functions.unlock(
        channel_identifier, B, A,
        pending_transfers_tree.packed_transfers).call_and_transact({"from": A})

    # A gets back locked tokens
    assert (custom_token.functions.balanceOf(A).call() == vals_A.deposit -
            vals_A.transferred + vals_B.transferred)
def test_settle_wrong_balance_hash(
    web3: Web3,
    get_accounts: Callable,
    token_network: Contract,
    create_channel_and_deposit: Callable,
    close_and_update_channel: Callable,
    reveal_secrets: Callable,
) -> None:
    """Calling settleChannel() with various wrong arguments and see failures"""
    (A, B) = get_accounts(2)
    vals_A = ChannelValues(
        deposit=35,
        withdrawn=0,
        transferred=5,
        locked_amounts=LockedAmounts(claimable_locked=10,
                                     unclaimable_locked=2),
    )
    vals_B = ChannelValues(
        deposit=40,
        withdrawn=0,
        transferred=15,
        locked_amounts=LockedAmounts(claimable_locked=5, unclaimable_locked=4),
    )
    channel_identifier = create_channel_and_deposit(A, B, vals_A.deposit,
                                                    vals_B.deposit)

    # Mock pending transfers data for A -> B
    pending_transfers_tree_A = get_pending_transfers_tree_with_generated_lists(
        web3,
        unlockable_amount=vals_A.locked_amounts.claimable_locked,
        expired_amount=vals_A.locked_amounts.unclaimable_locked,
    )
    vals_A.locksroot = pending_transfers_tree_A.hash_of_packed_transfers
    # Reveal A's secrets.
    reveal_secrets(A, pending_transfers_tree_A.unlockable)

    # Mock pending transfers data for B -> A
    pending_transfers_tree_B = get_pending_transfers_tree_with_generated_lists(
        web3,
        unlockable_amount=vals_B.locked_amounts.claimable_locked,
        expired_amount=vals_B.locked_amounts.unclaimable_locked,
    )
    vals_B.locksroot = pending_transfers_tree_B.hash_of_packed_transfers
    # Reveal B's secrets
    reveal_secrets(B, pending_transfers_tree_B.unlockable)

    close_and_update_channel(channel_identifier, A, vals_A, B, vals_B)

    mine_blocks(web3, TEST_SETTLE_TIMEOUT_MIN + 1)

    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, B, vals_A, A, vals_B)

    vals_A_fail = deepcopy(vals_A)
    vals_A_fail.transferred += 1
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A_fail, B,
                    vals_B)

    vals_A_fail.transferred = 0
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A_fail, B,
                    vals_B)

    vals_A_fail.transferred = UINT256_MAX
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, B, vals_B, A,
                    vals_A_fail)

    vals_A_fail = deepcopy(vals_A)
    vals_A_fail.locked_amounts.claimable_locked += 1
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A_fail, B,
                    vals_B)

    vals_A_fail.locked_amounts.claimable_locked = 0
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A_fail, B,
                    vals_B)

    vals_A_fail.locked_amounts.unclaimable_locked = 0
    vals_A_fail.locked_amounts.claimable_locked = UINT256_MAX
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, B, vals_B, A,
                    vals_A_fail)

    vals_A_fail = deepcopy(vals_A)
    vals_A_fail.locksroot = LOCKSROOT_OF_NO_LOCKS
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A_fail, B,
                    vals_B)

    vals_A_fail.locksroot = fake_bytes(32, "01")
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A_fail, B,
                    vals_B)

    vals_B_fail = deepcopy(vals_B)
    vals_B_fail.transferred += 1
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B,
                    vals_B_fail)

    vals_B_fail.transferred = 0
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, B, vals_B_fail, A,
                    vals_A)

    vals_B_fail.transferred = UINT256_MAX
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B,
                    vals_B_fail)

    vals_B_fail = deepcopy(vals_B)
    vals_B_fail.locked_amounts.claimable_locked += 1
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B,
                    vals_B_fail)

    vals_B_fail.locked_amounts.claimable_locked = 0
    with pytest.raises(AssertionError):
        call_settle(token_network, channel_identifier, B, vals_B_fail, A,
                    vals_A)

    vals_B_fail.locked_amounts.unclaimable_locked = 0
    vals_B_fail.locked_amounts.claimable_locked = UINT256_MAX
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B,
                    vals_B_fail)

    vals_B_fail = deepcopy(vals_B)
    vals_B_fail.locksroot = LOCKSROOT_OF_NO_LOCKS
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B,
                    vals_B_fail)

    vals_B_fail.locksroot = fake_bytes(32, "01")
    with pytest.raises(TransactionFailed):
        call_settle(token_network, channel_identifier, A, vals_A, B,
                    vals_B_fail)

    # Channel is settled
    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)
def test_settle_channel_state(
    web3: Web3,
    get_accounts: Callable,
    custom_token: Contract,
    token_network: Contract,
    create_channel_and_deposit: Callable,
    withdraw_channel: Callable,
    close_and_update_channel: Callable,
    settle_state_tests: Callable,
) -> None:
    """settleChannel() with some balance proofs"""
    (A, B) = get_accounts(2)
    vals_A = ChannelValues(
        deposit=40,
        withdrawn=10,
        transferred=20020,
        locked_amounts=LockedAmounts(claimable_locked=3, unclaimable_locked=4),
    )
    vals_B = ChannelValues(
        deposit=35,
        withdrawn=5,
        transferred=20030,
        locked_amounts=LockedAmounts(claimable_locked=2, unclaimable_locked=3),
    )

    pending_transfers_tree_A = get_pending_transfers_tree_with_generated_lists(
        web3,
        unlockable_amount=vals_A.locked_amounts.claimable_locked,
        expired_amount=vals_A.locked_amounts.unclaimable_locked,
    )
    pending_transfers_tree_B = get_pending_transfers_tree_with_generated_lists(
        web3,
        unlockable_amount=vals_B.locked_amounts.claimable_locked,
        expired_amount=vals_B.locked_amounts.unclaimable_locked,
    )
    vals_A.locksroot = pending_transfers_tree_A.hash_of_packed_transfers
    vals_B.locksroot = pending_transfers_tree_B.hash_of_packed_transfers

    channel_identifier = create_channel_and_deposit(A, B, vals_A.deposit,
                                                    vals_B.deposit)
    withdraw_channel(channel_identifier, A, vals_A.withdrawn, UINT256_MAX, B)
    withdraw_channel(channel_identifier, B, vals_B.withdrawn, UINT256_MAX, A)
    close_and_update_channel(channel_identifier, A, vals_A, B, vals_B)

    mine_blocks(web3, TEST_SETTLE_TIMEOUT_MIN + 1)

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)

    # Balance & state tests
    settle_state_tests(
        channel_identifier,
        A,
        vals_A,
        B,
        vals_B,
        pre_balance_A,
        pre_balance_B,
        pre_balance_contract,
    )

    # Some manual checks for the final balances, in case the settlement algorithms
    # used in `settle_state_tests` are incorrect

    # FIXME after setTotalWithdraw is implemented again
    post_balance_A = pre_balance_A + 33
    post_balance_B = pre_balance_B + 15
    post_balance_contract = pre_balance_contract - 48

    assert custom_token.functions.balanceOf(A).call() == post_balance_A
    assert custom_token.functions.balanceOf(B).call() == post_balance_B
    assert custom_token.functions.balanceOf(
        token_network.address).call() == post_balance_contract
def test_close_channel_state(
    web3: Web3,
    custom_token: Contract,
    token_network: Contract,
    create_channel: Callable,
    channel_deposit: Callable,
    get_accounts: Callable,
    get_block: Callable,
    create_balance_proof: Callable,
    txn_cost: Callable,
    create_balance_proof_countersignature: Callable,
) -> None:
    """ Observe the effect of a successful closeChannel

    This test compares the state of the channel and the balances of Ethereum
    accounts before/after a successful closeChannel call.
    """
    (A, B) = get_accounts(2)
    settle_timeout = TEST_SETTLE_TIMEOUT_MIN
    vals_B = ChannelValues(
        deposit=20,
        transferred=5,
        locksroot=fake_bytes(32, "03"),
        locked_amounts=LockedAmounts(claimable_locked=3, unclaimable_locked=4),
        nonce=3,
    )

    # Create channel and deposit
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, B, vals_B.deposit, A)

    # Check the state of the openned channel
    (settle_block_number,
     state) = token_network.functions.getChannelInfo(channel_identifier, A,
                                                     B).call()
    assert settle_block_number == settle_timeout
    assert state == ChannelState.OPENED

    (
        _,
        _,
        A_is_the_closer,
        A_balance_hash,
        A_nonce,
        _,
        _,
    ) = token_network.functions.getChannelParticipantInfo(
        channel_identifier, A, B).call()
    assert A_is_the_closer is False
    assert A_balance_hash == EMPTY_BALANCE_HASH
    assert A_nonce == 0
    (
        _,
        _,
        B_is_the_closer,
        B_balance_hash,
        B_nonce,
        _,
        _,
    ) = token_network.functions.getChannelParticipantInfo(
        channel_identifier, B, A).call()
    assert B_is_the_closer is False
    assert B_balance_hash == EMPTY_BALANCE_HASH
    assert B_nonce == 0

    pre_eth_balance_A = web3.eth.getBalance(A)
    pre_eth_balance_B = web3.eth.getBalance(B)
    pre_eth_balance_contract = web3.eth.getBalance(token_network.address)
    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # Create a balance proof
    balance_proof_B = create_balance_proof(
        channel_identifier,
        B,
        vals_B.transferred,
        vals_B.locked_amounts.locked,
        vals_B.nonce,
        vals_B.locksroot,
    )
    closing_sig_A = create_balance_proof_countersignature(
        A, channel_identifier, MessageTypeId.BALANCE_PROOF, *balance_proof_B)

    txn_hash = token_network.functions.closeChannel(
        channel_identifier, B, A, *balance_proof_B,
        closing_sig_A).call_and_transact({"from": A})

    # Test that no balances have changed.
    # There are no transfers to be made in closeChannel.
    assert web3.eth.getBalance(A) == pre_eth_balance_A - txn_cost(txn_hash)
    assert web3.eth.getBalance(B) == pre_eth_balance_B
    assert web3.eth.getBalance(
        token_network.address) == pre_eth_balance_contract
    assert custom_token.functions.balanceOf(A).call() == pre_balance_A
    assert custom_token.functions.balanceOf(B).call() == pre_balance_B
    assert custom_token.functions.balanceOf(
        token_network.address).call() == pre_balance_contract

    (settle_block_number,
     state) = token_network.functions.getChannelInfo(channel_identifier, A,
                                                     B).call()
    assert settle_block_number == settle_timeout + get_block(txn_hash)
    assert state == ChannelState.CLOSED

    (
        _,
        _,
        A_is_the_closer,
        A_balance_hash,
        A_nonce,
        _,
        _,
    ) = token_network.functions.getChannelParticipantInfo(
        channel_identifier, A, B).call()
    assert A_is_the_closer is True
    assert A_balance_hash == EMPTY_BALANCE_HASH
    assert A_nonce == 0

    (
        _,
        _,
        B_is_the_closer,
        B_balance_hash,
        B_nonce,
        _,
        _,
    ) = token_network.functions.getChannelParticipantInfo(
        channel_identifier, B, A).call()
    assert B_is_the_closer is False
    assert B_balance_hash == balance_proof_B[0]
    assert B_nonce == vals_B.nonce
def test_close_nonce_zero(
    get_accounts: Callable,
    token_network: Contract,
    create_channel: Callable,
    create_balance_proof: Callable,
    create_balance_proof_countersignature: Callable,
    event_handler: Callable,
) -> None:
    """ closeChannel with a balance proof with nonce zero should not change the channel state """
    (A, B) = get_accounts(2)
    vals_B = ChannelValues(
        deposit=20,
        transferred=5,
        locksroot=fake_bytes(32, "03"),
        locked_amounts=LockedAmounts(claimable_locked=3, unclaimable_locked=4),
        nonce=0,
    )
    # Create channel and deposit
    channel_identifier = create_channel(A, B)[0]

    # Create balance proofs
    balance_proof_B = create_balance_proof(
        channel_identifier,
        B,
        vals_B.transferred,
        vals_B.locked_amounts.locked,
        vals_B.nonce,
        vals_B.locksroot,
    )
    close_sig_A = create_balance_proof_countersignature(
        A, channel_identifier, MessageTypeId.BALANCE_PROOF, *balance_proof_B)

    (
        _,
        _,
        B_is_the_closer,
        B_balance_hash,
        B_nonce,
        _,
        _,
    ) = token_network.functions.getChannelParticipantInfo(
        channel_identifier, B, A).call()
    assert B_is_the_closer is False
    assert B_balance_hash == EMPTY_BALANCE_HASH
    assert B_nonce == 0

    ev_handler = event_handler(token_network)

    close_tx = token_network.functions.closeChannel(
        channel_identifier, B, A, *balance_proof_B,
        close_sig_A).call_and_transact({"from": A})

    ev_handler.add(
        close_tx,
        ChannelEvent.CLOSED,
        check_channel_closed(channel_identifier, A, 0, balance_proof_B[0]),
    )
    ev_handler.check()

    # Even though we somehow provide valid values for the balance proof, they are not taken into
    # consideration if the nonce is 0.
    # The Raiden client enforces that the nonce is > 0 if off-chain transfers are made.
    (
        _,
        _,
        B_is_the_closer,
        B_balance_hash,
        B_nonce,
        _,
        _,
    ) = token_network.functions.getChannelParticipantInfo(
        channel_identifier, B, A).call()
    assert B_is_the_closer is False
    assert B_balance_hash == EMPTY_BALANCE_HASH
    assert B_nonce == 0
def test_deprecation_switch_settle(
    web3: Web3,
    get_accounts: Callable,
    token_network: Contract,
    custom_token: Contract,
    reveal_secrets: Callable,
    create_channel: Callable,
    channel_deposit: Callable,
    close_and_update_channel: Callable,
) -> None:
    """ Channel close and settlement still work after the depracation switch is turned on """
    deprecation_executor = token_network.functions.deprecation_executor().call(
    )
    (A, B) = get_accounts(2)
    deposit = 100

    (vals_A, vals_B) = (
        ChannelValues(
            deposit=deposit,
            withdrawn=0,
            transferred=5,
            locked_amounts=LockedAmounts(claimable_locked=2,
                                         unclaimable_locked=4),
        ),
        ChannelValues(
            deposit=deposit,
            withdrawn=0,
            transferred=10,
            locked_amounts=LockedAmounts(claimable_locked=4,
                                         unclaimable_locked=6),
        ),
    )

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    channel_identifier = create_channel(A, B)[0]
    channel_deposit(channel_identifier, A, vals_A.deposit, B)
    channel_deposit(channel_identifier, B, vals_B.deposit, A)

    # Mock pending transfers data for A -> B
    pending_transfers_tree_A = get_pending_transfers_tree_with_generated_lists(
        web3,
        unlockable_amount=vals_A.locked_amounts.claimable_locked,
        expired_amount=vals_A.locked_amounts.unclaimable_locked,
    )
    vals_A.locksroot = pending_transfers_tree_A.hash_of_packed_transfers
    # Reveal A's secrets.
    reveal_secrets(A, pending_transfers_tree_A.unlockable)

    # Mock pending transfers data for B -> A
    pending_transfers_tree_B = get_pending_transfers_tree_with_generated_lists(
        web3,
        unlockable_amount=vals_B.locked_amounts.claimable_locked,
        expired_amount=vals_B.locked_amounts.unclaimable_locked,
    )
    vals_B.locksroot = pending_transfers_tree_B.hash_of_packed_transfers
    # Reveal B's secrets
    reveal_secrets(B, pending_transfers_tree_B.unlockable)

    # Set the deprecation switch to true
    token_network.functions.deprecate().call_and_transact(
        {"from": deprecation_executor})
    assert token_network.functions.safety_deprecation_switch().call() is True

    # We need to make sure we can still close, settle & unlock the channels
    close_and_update_channel(channel_identifier, A, vals_A, B, vals_B)
    web3.testing.mine(TEST_SETTLE_TIMEOUT_MIN + 1)

    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)

    # Unlock B's pending transfers that were sent to A
    token_network.functions.unlock(
        channel_identifier, A, B,
        pending_transfers_tree_B.packed_transfers).call_and_transact()

    # Unlock A's pending transfers that were sent to B
    token_network.functions.unlock(
        channel_identifier, B, A,
        pending_transfers_tree_A.packed_transfers).call_and_transact()

    assert custom_token.functions.balanceOf(A).call() == pre_balance_A + 107
    assert custom_token.functions.balanceOf(B).call() == pre_balance_B + 93
    assert custom_token.functions.balanceOf(
        token_network.address).call() == pre_balance_contract
Beispiel #9
0
def test_channel_unlock_both_participants(
    web3,
    custom_token,
    token_network,
    secret_registry_contract,
    create_channel,
    channel_deposit,
    get_accounts,
    close_and_update_channel,
    reveal_secrets,
):
    """ A scenario where both parties get some of the pending transfers """
    (A, B) = get_accounts(2)
    settle_timeout = 8

    values_A = ChannelValues(deposit=100, transferred=5)
    values_B = ChannelValues(deposit=100, transferred=40)

    # Create channel and deposit
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, A, values_A.deposit, B)
    channel_deposit(channel_identifier, B, values_B.deposit, A)

    # Mock pending transfers data for A
    pending_transfers_tree_A = get_pending_transfers_tree(
        web3, [1, 3, 5], [2, 4], settle_timeout)
    values_A.locksroot = pending_transfers_tree_A.merkle_root
    values_A.locked_amounts = LockedAmounts(
        claimable_locked=get_locked_amount(pending_transfers_tree_A.transfers))

    # Reveal A's secrets before settlement window ends
    reveal_secrets(A, pending_transfers_tree_A.unlockable)

    # Mock pending transfers data for B
    pending_transfers_tree_B = get_pending_transfers_tree(
        web3, [2, 4, 6], [5, 10], settle_timeout)
    values_B.locksroot = pending_transfers_tree_B.merkle_root
    values_B.locked_amounts = LockedAmounts(
        claimable_locked=get_locked_amount(pending_transfers_tree_B.transfers))

    # Reveal B's secrets before settlement window ends
    reveal_secrets(B, pending_transfers_tree_B.unlockable)

    close_and_update_channel(channel_identifier, A, values_A, B, values_B)

    # Settle channel
    web3.testing.mine(settle_timeout)

    call_settle(token_network, channel_identifier, A, values_A, B, values_B)

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # A unlock's
    token_network.functions.unlock(
        channel_identifier, A, B,
        pending_transfers_tree_B.packed_transfers).call_and_transact()

    # B unlock's
    token_network.functions.unlock(
        channel_identifier, B, A,
        pending_transfers_tree_A.packed_transfers).call_and_transact()

    balance_A = custom_token.functions.balanceOf(A).call()
    balance_B = custom_token.functions.balanceOf(B).call()
    balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # Unlocked pending transfers A -> B, that belong to B
    unlockable_A = get_unlocked_amount(
        secret_registry_contract, pending_transfers_tree_A.packed_transfers)

    # Expired pending transfers A -> B, that belong to A
    expired_A = get_locked_amount(pending_transfers_tree_A.expired)

    # Unlocked pending transfers B -> A, that belong to A
    unlockable_B = get_unlocked_amount(
        secret_registry_contract, pending_transfers_tree_B.packed_transfers)

    # Expired pending transfers B -> A, that belong to B
    expired_B = get_locked_amount(pending_transfers_tree_B.expired)

    # check that A and B both received the expected amounts
    assert balance_contract == (pre_balance_contract -
                                values_B.locked_amounts.locked -
                                values_A.locked_amounts.locked)
    assert balance_A == pre_balance_A + unlockable_B + expired_A
    assert balance_B == pre_balance_B + unlockable_A + expired_B
Beispiel #10
0
def test_channel_unlock_before_settlement_fails(
    web3,
    custom_token,
    token_network,
    create_channel,
    channel_deposit,
    get_accounts,
    close_and_update_channel,
    reveal_secrets,
):
    """ unlock() should not work before settlement """
    (A, B) = get_accounts(2)
    settle_timeout = 8

    values_A = ChannelValues(deposit=20, transferred=5)
    values_B = ChannelValues(deposit=30, transferred=40)

    # Create channel and deposit
    channel_identifier = create_channel(A, B, settle_timeout)[0]

    # Mock pending transfers data
    pending_transfers_tree = get_pending_transfers_tree(
        web3, [1, 3, 5], [2, 4], settle_timeout)
    values_B.locksroot = pending_transfers_tree.merkle_root
    values_B.locked_amounts = LockedAmounts(
        claimable_locked=get_locked_amount(pending_transfers_tree.transfers))

    # Reveal secrets before settlement window ends
    reveal_secrets(A, pending_transfers_tree.unlockable)

    # Unlock fails before channel is not settled
    with pytest.raises(TransactionFailed):
        token_network.functions.unlock(
            channel_identifier, A, B,
            pending_transfers_tree.packed_transfers).call()

    channel_deposit(channel_identifier, A, values_A.deposit, B)
    channel_deposit(channel_identifier, B, values_B.deposit, A)

    # Unlock fails before channel is not settled
    with pytest.raises(TransactionFailed):
        token_network.functions.unlock(
            channel_identifier, A, B,
            pending_transfers_tree.packed_transfers).call()

    close_and_update_channel(channel_identifier, A, values_A, B, values_B)

    # Unlock fails before settlement window is over and channel is not settled
    with pytest.raises(TransactionFailed):
        token_network.functions.unlock(
            channel_identifier, A, B,
            pending_transfers_tree.packed_transfers).call()

    # Settlement window must be over before settling the channel
    web3.testing.mine(settle_timeout)

    # Unlock fails before settle is called
    with pytest.raises(TransactionFailed):
        token_network.functions.unlock(
            channel_identifier, A, B,
            pending_transfers_tree.packed_transfers).call()

    # settle channel
    call_settle(token_network, channel_identifier, A, values_A, B, values_B)

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # Unlock works after channel is settled
    token_network.functions.unlock(
        channel_identifier, A, B,
        pending_transfers_tree.packed_transfers).call_and_transact()

    balance_A = custom_token.functions.balanceOf(A).call()
    balance_B = custom_token.functions.balanceOf(B).call()
    balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()
    assert balance_A == pre_balance_A + 9
    assert balance_B == pre_balance_B + 6
    assert balance_contract == pre_balance_contract - values_B.locked_amounts.locked
Beispiel #11
0
def test_channel_unlock_registered_expired_lock_refunds(
    web3,
    custom_token,
    token_network,
    secret_registry_contract,
    create_channel,
    channel_deposit,
    get_accounts,
    close_and_update_channel,
):
    """ unlock() should refund tokens locked with secrets revealed after the expiration """
    (A, B) = get_accounts(2)
    max_lock_expiration = 3
    settle_timeout = 8

    values_A = ChannelValues(deposit=20, transferred=5)
    values_B = ChannelValues(deposit=30, transferred=40)

    # Create channel and deposit
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, A, values_A.deposit, B)
    channel_deposit(channel_identifier, B, values_B.deposit, A)

    # Mock pending transfers data
    pending_transfers_tree = get_pending_transfers_tree(
        web3,
        [1, 3, 5],
        [2, 4],
        min_expiration_delta=max_lock_expiration - 2,
        max_expiration_delta=max_lock_expiration,
    )
    values_B.locksroot = pending_transfers_tree.merkle_root
    values_B.locked_amounts = LockedAmounts(
        claimable_locked=get_locked_amount(pending_transfers_tree.transfers))

    # Locks expire
    web3.testing.mine(max_lock_expiration)

    # Secrets are revealed before settlement window, but after expiration
    for (_, _, secrethash, secret) in pending_transfers_tree.unlockable:
        secret_registry_contract.functions.registerSecret(
            secret).call_and_transact({"from": A})
        assert (secret_registry_contract.functions.getSecretRevealBlockHeight(
            secrethash).call() == web3.eth.blockNumber)

    close_and_update_channel(channel_identifier, A, values_A, B, values_B)
    web3.testing.mine(settle_timeout)

    # settle channel
    call_settle(token_network, channel_identifier, A, values_A, B, values_B)

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # Unlock works after channel is settled
    token_network.functions.unlock(
        channel_identifier, A, B,
        pending_transfers_tree.packed_transfers).call_and_transact()

    balance_A = custom_token.functions.balanceOf(A).call()
    balance_B = custom_token.functions.balanceOf(B).call()
    balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # check that all tokens have been refunded, as locks have expired already
    assert balance_A == pre_balance_A
    assert balance_B == pre_balance_B + values_B.locked_amounts.locked
    assert balance_contract == pre_balance_contract - values_B.locked_amounts.locked
Beispiel #12
0
def test_channel_unlock(
    web3,
    custom_token,
    token_network,
    create_channel,
    channel_deposit,
    get_accounts,
    close_and_update_channel,
    reveal_secrets,
):
    """ unlock() on pending transfers with unlockable and expired locks should
    split the locked amount accordingly, to both parties """
    (A, B) = get_accounts(2)
    settle_timeout = 8

    values_A = ChannelValues(deposit=20, transferred=5)
    values_B = ChannelValues(deposit=30, transferred=40)

    # Create channel and deposit
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, A, values_A.deposit, B)
    channel_deposit(channel_identifier, B, values_B.deposit, A)

    # Mock pending transfers data
    pending_transfers_tree = get_pending_transfers_tree(
        web3, [1, 3, 5], [2, 4], settle_timeout)
    values_B.locksroot = pending_transfers_tree.merkle_root
    values_B.locked_amounts = LockedAmounts(
        claimable_locked=get_locked_amount(pending_transfers_tree.transfers))

    # Reveal secrets before settlement window ends
    reveal_secrets(A, pending_transfers_tree.unlockable)

    close_and_update_channel(channel_identifier, A, values_A, B, values_B)

    # Settlement window must be over before settling the channel
    web3.testing.mine(settle_timeout)

    call_settle(token_network, channel_identifier, A, values_A, B, values_B)

    pre_balance_A = custom_token.functions.balanceOf(A).call()
    pre_balance_B = custom_token.functions.balanceOf(B).call()
    pre_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    info_B = token_network.functions.getChannelParticipantInfo(
        channel_identifier, B, A).call()
    assert info_B[ParticipantInfoIndex.LOCKSROOT] == values_B.locksroot
    assert info_B[
        ParticipantInfoIndex.LOCKED_AMOUNT] == values_B.locked_amounts.locked

    # Unlock the tokens
    token_network.functions.unlock(
        channel_identifier, A, B,
        pending_transfers_tree.packed_transfers).call_and_transact()

    info_B = token_network.functions.getChannelParticipantInfo(
        channel_identifier, B, A).call()
    assert info_B[ParticipantInfoIndex.LOCKSROOT] == EMPTY_LOCKSROOT
    assert info_B[ParticipantInfoIndex.LOCKED_AMOUNT] == 0

    balance_A = custom_token.functions.balanceOf(A).call()
    balance_B = custom_token.functions.balanceOf(B).call()
    balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()
    assert balance_A == pre_balance_A + 9
    assert balance_B == pre_balance_B + 6
    assert balance_contract == pre_balance_contract - values_B.locked_amounts.locked
Beispiel #13
0
def test_unlock_channel_event(
    web3,
    token_network,
    secret_registry_contract,
    create_channel,
    channel_deposit,
    get_accounts,
    close_and_update_channel,
    reveal_secrets,
    event_handler,
):
    """ Successful unlock() should cause an UNLOCKED event """
    (A, B) = get_accounts(2)
    settle_timeout = 8

    values_A = ChannelValues(deposit=20, transferred=5)
    values_B = ChannelValues(deposit=30, transferred=40)

    # Create channel and deposit
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, A, values_A.deposit, B)
    channel_deposit(channel_identifier, B, values_B.deposit, A)

    # Mock pending transfers data
    pending_transfers_tree = get_pending_transfers_tree(
        web3, [1, 3, 5], [2, 4], settle_timeout + 100)
    values_B.locksroot = pending_transfers_tree.merkle_root
    values_B.locked_amounts = LockedAmounts(
        claimable_locked=get_locked_amount(pending_transfers_tree.transfers))

    # Reveal secrets before settlement window ends
    reveal_secrets(A, pending_transfers_tree.unlockable)

    close_and_update_channel(channel_identifier, A, values_A, B, values_B)

    # Settlement window must be over before settling the channel
    web3.testing.mine(settle_timeout)

    call_settle(token_network, channel_identifier, A, values_A, B, values_B)

    ev_handler = event_handler(token_network)

    # Unlock the tokens
    txn_hash = token_network.functions.unlock(
        channel_identifier, A, B,
        pending_transfers_tree.packed_transfers).call_and_transact()

    unlocked_amount = get_unlocked_amount(
        secret_registry_contract, pending_transfers_tree.packed_transfers)

    # Add event
    ev_handler.add(
        txn_hash,
        ChannelEvent.UNLOCKED,
        check_channel_unlocked(
            channel_identifier,
            A,
            B,
            values_B.locksroot,
            unlocked_amount,
            values_B.locked_amounts.locked - unlocked_amount,
        ),
    )

    # Check that event was properly emitted
    ev_handler.check()
Beispiel #14
0
# we cannot determine and guarantee corectness. There are specific constraints that the
# Raiden client must enforce that guarantee correctness.

# For all valid last balance proofs provided we have manually constructed a suit of old balance
# proof pairs that could be used for attacks (documented edge cases).
# We will test that using old balance proofs does not result in cheating, therefore the attacker
# (participant who provides the old balance proof) must not receive more tokens than in the case
# where he provides a `valid last` balance proof.
channel_settle_test_values = [
    {
        "valid_last": (
            ChannelValues(
                deposit=35,
                withdrawn=5,
                transferred=20020,
                locked_amounts=LockedAmounts(claimable_locked=3,
                                             unclaimable_locked=1),
            ),
            ChannelValues(
                deposit=40,
                withdrawn=10,
                transferred=20030,
                locked_amounts=LockedAmounts(claimable_locked=4,
                                             unclaimable_locked=2),
            ),
        ),
        # participant2 provides a valid but old balance proof of participant1
        "old_last": [
            # participant2 does not send participant1's balance proof
            ChannelValues(deposit=35,
                          withdrawn=5,
                          transferred=0,
Beispiel #15
0
# we cannot determine and guarantee corectness. There are specific constraints that the
# Raiden client must enforce that guarantee correctness.

# For all valid last balance proofs provided we have manually constructed a suit of old balance
# proof pairs that could be used for attacks (documented edge cases).
# We will test that using old balance proofs does not result in cheating, therefore the attacker
# (participant who provides the old balance proof) must not receive more tokens than in the case
# where he provides a `valid last` balance proof.
channel_settle_test_values = [
    {
        "valid_last": (
            ChannelValues(
                deposit=35,
                withdrawn=5,
                transferred=20020,
                locked_amounts=LockedAmounts(claimable_locked=3, unclaimable_locked=1),
            ),
            ChannelValues(
                deposit=40,
                withdrawn=10,
                transferred=20030,
                locked_amounts=LockedAmounts(claimable_locked=4, unclaimable_locked=2),
            ),
        ),
        # participant2 provides a valid but old balance proof of participant1
        "old_last": [
            # participant2 does not send participant1's balance proof
            ChannelValues(deposit=35, withdrawn=5, transferred=0, locked_amounts=LockedAmounts()),
            # participant2 provides an old participant1 balance proof with a smaller
            # transferred amount
            ChannelValues(