def test_update_not_allowed_after_settlement_period(
    token_network,
    create_channel,
    channel_deposit,
    get_accounts,
    create_balance_proof,
    create_balance_proof_update_signature,
    web3,
):
    """ updateNonClosingBalanceProof cannot be called after the settlement period. """
    (A, B) = get_accounts(2)
    settle_timeout = TEST_SETTLE_TIMEOUT_MIN
    deposit_A = 20
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, A, deposit_A, B)
    balance_proof_A = create_balance_proof(channel_identifier, A, 10, 0, 5, fake_bytes(32, "02"))
    balance_proof_B = create_balance_proof(channel_identifier, B, 5, 0, 3, fake_bytes(32, "02"))
    balance_proof_update_signature_B = create_balance_proof_update_signature(
        B, channel_identifier, *balance_proof_A
    )
    token_network.functions.closeChannel(
        channel_identifier, B, *balance_proof_B
    ).call_and_transact({"from": A})
    web3.testing.mine(settle_timeout + 1)
    with pytest.raises(TransactionFailed):
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier, A, B, *balance_proof_A, balance_proof_update_signature_B
        ).call({"from": A})
def test_update_not_allowed_for_the_closing_address(
        token_network,
        create_channel,
        channel_deposit,
        get_accounts,
        create_balance_proof,
        create_balance_proof_update_signature,
):
    """ Closing address cannot call updateNonClosingBalanceProof. """
    (A, B, M) = get_accounts(3)
    settle_timeout = TEST_SETTLE_TIMEOUT_MIN
    deposit_A = 20
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, A, deposit_A, B)

    # Some balance proof from B
    balance_proof_B_0 = create_balance_proof(channel_identifier, B, 5, 0, 3, fake_bytes(32, '02'))

    # Later balance proof, higher transferred amount, higher nonce
    balance_proof_B_1 = create_balance_proof(channel_identifier, B, 10, 0, 4, fake_bytes(32, '02'))

    # B's signature on the update message is valid
    balance_proof_update_signature_B = create_balance_proof_update_signature(
        B,
        channel_identifier,
        *balance_proof_B_1,
    )

    # A closes with the first balance proof
    token_network.functions.closeChannel(
        channel_identifier,
        B,
        *balance_proof_B_0,
    ).transact({'from': A})

    # Someone wants to update with later balance proof - not possible
    with pytest.raises(TransactionFailed):
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier,
            A,
            B,
            *balance_proof_B_1,
            balance_proof_update_signature_B,
        ).transact({'from': A})
    with pytest.raises(TransactionFailed):
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier,
            A,
            B,
            *balance_proof_B_1,
            balance_proof_update_signature_B,
        ).transact({'from': B})
    with pytest.raises(TransactionFailed):
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier,
            A,
            B,
            *balance_proof_B_1,
            balance_proof_update_signature_B,
        ).transact({'from': M})
def test_update_not_allowed_after_settlement_period(
    token_network: Contract,
    create_channel: Callable,
    channel_deposit: Callable,
    get_accounts: Callable,
    create_balance_proof: Callable,
    create_balance_proof_countersignature: Callable,
    web3: Web3,
) -> None:
    """ updateNonClosingBalanceProof cannot be called after the settlement period. """
    (A, B) = get_accounts(2)
    settle_timeout = TEST_SETTLE_TIMEOUT_MIN
    deposit_A = 20
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, A, deposit_A, B)
    balance_proof_A = create_balance_proof(channel_identifier, A, 10, 0, 5, fake_bytes(32, "02"))
    balance_proof_B = create_balance_proof(channel_identifier, B, 5, 0, 3, fake_bytes(32, "02"))
    closing_sig_A = create_balance_proof_countersignature(
        A, channel_identifier, MessageTypeId.BALANCE_PROOF, *balance_proof_B
    )
    balance_proof_update_signature_B = create_balance_proof_countersignature(
        B, channel_identifier, MessageTypeId.BALANCE_PROOF_UPDATE, *balance_proof_A
    )
    token_network.functions.closeChannel(
        channel_identifier, B, A, *balance_proof_B, closing_sig_A
    ).call_and_transact({"from": A})
    web3.testing.mine(settle_timeout + 1)
    with pytest.raises(TransactionFailed):
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier, A, B, *balance_proof_A, balance_proof_update_signature_B
        ).call({"from": A})
def test_update_wrong_nonce_fail(
    token_network: Contract,
    create_channel: Callable,
    channel_deposit: Callable,
    get_accounts: Callable,
    create_balance_proof: Callable,
    create_balance_proof_update_signature: Callable,
    update_state_tests: Callable,
) -> None:
    (A, B, Delegate) = get_accounts(3)
    settle_timeout = 6
    deposit_A = 20
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, A, deposit_A, B)
    balance_proof_A = create_balance_proof(channel_identifier, A, 10, 0, 5, fake_bytes(32, "02"))
    balance_proof_B = create_balance_proof(channel_identifier, B, 5, 0, 3, fake_bytes(32, "02"))
    balance_proof_update_signature_B = create_balance_proof_update_signature(
        B, channel_identifier, *balance_proof_A
    )
    txn_hash1 = token_network.functions.closeChannel(
        channel_identifier, B, *balance_proof_B
    ).call_and_transact({"from": A})

    token_network.functions.updateNonClosingBalanceProof(
        channel_identifier, A, B, *balance_proof_A, balance_proof_update_signature_B
    ).call_and_transact({"from": Delegate})

    # updateNonClosingBalanceProof should fail for the same nonce as provided previously
    with pytest.raises(TransactionFailed):
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier, A, B, *balance_proof_A, balance_proof_update_signature_B
        ).call({"from": Delegate})
    balance_proof_A_same_nonce = create_balance_proof(
        channel_identifier, A, 12, 2, balance_proof_A[1], fake_bytes(32, "03")
    )
    with pytest.raises(TransactionFailed):
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier, A, B, *balance_proof_A_same_nonce, balance_proof_update_signature_B
        ).call({"from": Delegate})

    balance_proof_A_lower_nonce = create_balance_proof(
        channel_identifier, A, 10, 0, 4, fake_bytes(32, "02")
    )

    balance_proof_update_signature_B = create_balance_proof_update_signature(
        B, channel_identifier, *balance_proof_A_lower_nonce
    )
    with pytest.raises(TransactionFailed):
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier,
            A,
            B,
            *balance_proof_A_lower_nonce,
            balance_proof_update_signature_B,
        ).call({"from": A})

    update_state_tests(
        channel_identifier, A, balance_proof_A, B, balance_proof_B, settle_timeout, txn_hash1
    )
Esempio n. 5
0
def common_settle_state_tests(
    custom_token,
    token_network,
    channel_identifier,
    A,
    balance_A,
    B,
    balance_B,
    pre_account_balance_A,
    pre_account_balance_B,
    pre_balance_contract,
):
    # Make sure the correct amount of tokens has been transferred
    account_balance_A = custom_token.functions.balanceOf(A).call()
    account_balance_B = custom_token.functions.balanceOf(B).call()
    balance_contract = custom_token.functions.balanceOf(token_network.address).call()
    assert account_balance_A == pre_account_balance_A + balance_A
    assert account_balance_B == pre_account_balance_B + balance_B
    assert balance_contract == pre_balance_contract - balance_A - balance_B

    # Make sure channel data has been removed
    assert (
        token_network.functions.participants_hash_to_channel_identifier(
            get_participants_hash(A, B)
        ).call()
        == 0
    )

    # Make sure participant data has been removed
    (
        A_deposit,
        A_withdrawn,
        A_is_the_closer,
        A_balance_hash,
        A_nonce,
        _,
        _,
    ) = token_network.functions.getChannelParticipantInfo(channel_identifier, A, B).call()
    assert A_deposit == 0
    assert A_withdrawn == 0
    assert A_is_the_closer == 0
    assert A_balance_hash == fake_bytes(32)
    assert A_nonce == 0

    (
        B_deposit,
        B_withdrawn,
        B_is_the_closer,
        B_balance_hash,
        B_nonce,
        _,
        _,
    ) = token_network.functions.getChannelParticipantInfo(channel_identifier, B, A).call()
    assert B_deposit == 0
    assert B_withdrawn == 0
    assert B_is_the_closer == 0
    assert B_balance_hash == fake_bytes(32)
    assert B_nonce == 0
Esempio n. 6
0
    def get(
        channel_identifier: int,
        participant1: HexAddress,
        participant1_values: ChannelValues,
        participant2: HexAddress,
        participant2_values: ChannelValues,
    ) -> None:
        nonce1 = 5
        nonce2 = 7
        additional_hash1 = fake_bytes(32)
        additional_hash2 = fake_bytes(32)

        balance_proof_1 = create_balance_proof(
            channel_identifier,
            participant1,
            participant1_values.transferred,
            participant1_values.locked_amounts.locked,
            nonce1,
            participant1_values.locksroot,
            additional_hash1,
        )
        balance_proof_2 = create_balance_proof(
            channel_identifier,
            participant2,
            participant2_values.transferred,
            participant2_values.locked_amounts.locked,
            nonce2,
            participant2_values.locksroot,
            additional_hash2,
        )
        balance_proof_close_signature_1 = create_balance_proof_countersignature(
            participant=participant1,
            channel_identifier=channel_identifier,
            msg_type=MessageTypeId.BALANCE_PROOF,
            **balance_proof_2._asdict(),
        )
        balance_proof_update_signature_2 = create_balance_proof_countersignature(
            participant=participant2,
            channel_identifier=channel_identifier,
            msg_type=MessageTypeId.BALANCE_PROOF_UPDATE,
            **balance_proof_1._asdict(),
        )

        token_network.functions.closeChannel(
            channel_identifier,
            participant2,
            participant1,
            *balance_proof_2._asdict().values(),
            balance_proof_close_signature_1,
        ).call_and_transact({"from": participant1})

        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier,
            participant1,
            participant2,
            *balance_proof_1._asdict().values(),
            balance_proof_update_signature_2,
        ).call_and_transact({"from": participant2})
def test_update_channel_state(
    web3: Web3,
    custom_token: Contract,
    token_network: Contract,
    create_channel: Callable,
    channel_deposit: Callable,
    get_accounts: Callable,
    create_balance_proof: Callable,
    create_balance_proof_countersignature: Callable,
    update_state_tests: Callable,
    txn_cost: Callable,
) -> None:
    """ A successful updateNonClosingBalanceProof() call should not change token/ETH balances """
    (A, B, Delegate) = get_accounts(3)
    settle_timeout = 6
    deposit_A = 20
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, A, deposit_A, B)
    balance_proof_A = create_balance_proof(channel_identifier, A, 10, 0, 5, fake_bytes(32, "02"))
    balance_proof_B = create_balance_proof(channel_identifier, B, 5, 0, 3, fake_bytes(32, "02"))
    closing_sig_A = create_balance_proof_countersignature(
        A, channel_identifier, MessageTypeId.BALANCE_PROOF, *balance_proof_B
    )
    balance_proof_update_signature_B = create_balance_proof_countersignature(
        B, channel_identifier, MessageTypeId.BALANCE_PROOF_UPDATE, *balance_proof_A
    )

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

    pre_eth_balance_A = web3.eth.getBalance(A)
    pre_eth_balance_B = web3.eth.getBalance(B)
    pre_eth_balance_delegate = web3.eth.getBalance(Delegate)
    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_delegate = custom_token.functions.balanceOf(Delegate).call()
    pre_balance_contract = custom_token.functions.balanceOf(token_network.address).call()

    txn_hash = token_network.functions.updateNonClosingBalanceProof(
        channel_identifier, A, B, *balance_proof_A, balance_proof_update_signature_B
    ).call_and_transact({"from": Delegate})

    # Test that no balances have changed.
    # There are no transfers to be made in updateNonClosingBalanceProof.
    assert web3.eth.getBalance(A) == pre_eth_balance_A
    assert web3.eth.getBalance(B) == pre_eth_balance_B
    assert web3.eth.getBalance(Delegate) == pre_eth_balance_delegate - txn_cost(txn_hash)
    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(Delegate).call() == pre_balance_delegate
    assert custom_token.functions.balanceOf(token_network.address).call() == pre_balance_contract

    update_state_tests(
        channel_identifier, A, balance_proof_A, B, balance_proof_B, settle_timeout, txn_hash1
    )
def test_settle_timeout_inrange(
    token_network: Contract,
    get_accounts: Callable,
    web3: Web3,
    create_close_signature_for_no_balance_proof: Callable,
) -> None:
    """ The TokenNetwork constructor must enforce that settle timeout is in
    the valid range.

    Also asserts that the constants.py and the netting channel contract values
    are synched.
    """
    (A, B) = get_accounts(2)

    small_settle_timeout = TEST_SETTLE_TIMEOUT_MIN - 1
    large_settle_timeout = TEST_SETTLE_TIMEOUT_MAX + 1

    with pytest.raises(TransactionFailed):
        token_network.functions.openChannel(A, B, small_settle_timeout).call()

    with pytest.raises(TransactionFailed):
        token_network.functions.openChannel(A, B, large_settle_timeout).call()

    token_network.functions.openChannel(A, B, TEST_SETTLE_TIMEOUT_MIN).call_and_transact()
    channel_identifier = token_network.functions.getChannelIdentifier(A, B).call()
    (settle_block_number, _) = token_network.functions.getChannelInfo(
        channel_identifier, A, B
    ).call()

    assert settle_block_number == TEST_SETTLE_TIMEOUT_MIN

    closing_sig = create_close_signature_for_no_balance_proof(A, channel_identifier)
    token_network.functions.closeChannel(
        channel_identifier=channel_identifier,
        non_closing_participant=B,
        closing_participant=A,
        balance_hash=fake_bytes(32),
        nonce=0,
        additional_hash=fake_bytes(32),
        non_closing_signature=fake_bytes(65),
        closing_signature=closing_sig,
    ).call_and_transact({"from": A})
    web3.testing.mine(TEST_SETTLE_TIMEOUT_MIN + 1)
    token_network.functions.settleChannel(
        channel_identifier, A, 0, 0, LOCKSROOT_OF_NO_LOCKS, B, 0, 0, LOCKSROOT_OF_NO_LOCKS
    ).call_and_transact({"from": A})
    token_network.functions.openChannel(A, B, TEST_SETTLE_TIMEOUT_MAX).call_and_transact()
    channel_identifier = token_network.functions.getChannelIdentifier(A, B).call()
    (settle_block_number, _) = token_network.functions.getChannelInfo(
        channel_identifier, A, B
    ).call()

    assert settle_block_number == TEST_SETTLE_TIMEOUT_MAX
def test_update_wrong_signatures(
    token_network: Contract,
    create_channel: Callable,
    channel_deposit: Callable,
    get_accounts: Callable,
    create_balance_proof: Callable,
    create_balance_proof_countersignature: Callable,
    create_close_signature_for_no_balance_proof: Callable,
) -> None:
    """ updateNonClosingBalanceProof() should fail with wrong signatures """
    (A, B, C) = get_accounts(3)
    channel_identifier = create_channel(A, B)[0]
    channel_deposit(channel_identifier, A, 25, B)

    balance_proof_A = create_balance_proof(channel_identifier, A, 10, 0, 5, fake_bytes(32, "02"))
    balance_proof_A_fake = create_balance_proof(
        channel_identifier, A, 10, 0, 5, fake_bytes(32, "02"), signer=C
    )

    balance_proof_update_signature_B = create_balance_proof_countersignature(
        B, channel_identifier, MessageTypeId.BALANCE_PROOF_UPDATE, *balance_proof_A
    )
    balance_proof_update_signature_B_fake = create_balance_proof_countersignature(
        C, channel_identifier, MessageTypeId.BALANCE_PROOF_UPDATE, *balance_proof_A
    )

    # Close the channel so updateNonClosingBalanceProof() is possible
    closing_sig = create_close_signature_for_no_balance_proof(A, channel_identifier)
    token_network.functions.closeChannel(
        channel_identifier,
        B,
        A,
        EMPTY_BALANCE_HASH,
        0,
        EMPTY_ADDITIONAL_HASH,
        EMPTY_SIGNATURE,
        closing_sig,
    ).call_and_transact({"from": A})

    with pytest.raises(TransactionFailed):
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier, A, B, *balance_proof_A_fake, balance_proof_update_signature_B
        ).call({"from": C})
    with pytest.raises(TransactionFailed):
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier, A, B, *balance_proof_A, balance_proof_update_signature_B_fake
        ).call({"from": C})

    # See a success to make sure that the above failures are not spurious
    token_network.functions.updateNonClosingBalanceProof(
        channel_identifier, A, B, *balance_proof_A, balance_proof_update_signature_B
    ).call_and_transact({"from": C})
Esempio n. 10
0
    def get(
        channel_identifier,
        participant1,
        participant1_values,
        participant2,
        participant2_values,
    ):
        nonce1 = 5
        nonce2 = 7
        additional_hash1 = fake_bytes(32)
        additional_hash2 = fake_bytes(32)

        balance_proof_1 = create_balance_proof(
            channel_identifier,
            participant1,
            participant1_values.transferred,
            participant1_values.locked,
            nonce1,
            participant1_values.locksroot,
            additional_hash1,
        )
        balance_proof_2 = create_balance_proof(
            channel_identifier,
            participant2,
            participant2_values.transferred,
            participant2_values.locked,
            nonce2,
            participant2_values.locksroot,
            additional_hash2,
        )
        balance_proof_update_signature_2 = create_balance_proof_update_signature(
            participant2,
            channel_identifier,
            *balance_proof_1,
        )

        token_network.functions.closeChannel(
            channel_identifier,
            participant2,
            *balance_proof_2,
        ).transact({'from': participant1})

        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier,
            participant1,
            participant2,
            *balance_proof_1,
            balance_proof_update_signature_2,
        ).transact({'from': participant2})
def test_update_notclosed_fail(
    get_accounts: Callable,
    token_network: Contract,
    create_channel: Callable,
    channel_deposit: Callable,
    create_balance_proof: Callable,
    create_balance_proof_countersignature: Callable,
) -> None:
    """ updateNonClosingBalanceProof() on an Opened channel should fail """
    (A, B, C) = get_accounts(3)
    channel_identifier = create_channel(A, B)[0]
    channel_deposit(channel_identifier, A, 25, B)

    balance_proof_A = create_balance_proof(channel_identifier, A, 10, 0, 5, fake_bytes(32, "02"))
    balance_proof_update_signature_B = create_balance_proof_countersignature(
        B, channel_identifier, MessageTypeId.BALANCE_PROOF_UPDATE, *balance_proof_A
    )

    (settle_block_number, state) = token_network.functions.getChannelInfo(
        channel_identifier, A, B
    ).call()
    assert settle_block_number > 0
    assert state == ChannelState.OPENED

    with pytest.raises(TransactionFailed):
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier, A, B, *balance_proof_A, balance_proof_update_signature_B
        ).call({"from": C})
Esempio n. 12
0
def test_close_wrong_signature(
    token_network,
    create_channel,
    channel_deposit,
    get_accounts,
    create_balance_proof,
):
    """ Closing a channel with a balance proof of the third party should fail """
    (A, B, C) = get_accounts(3)
    deposit_A = 6
    transferred_amount = 5
    nonce = 3
    locksroot = fake_bytes(32, '03')

    channel_identifier = create_channel(A, B)[0]
    channel_deposit(channel_identifier, A, deposit_A, B)

    # Create balance proofs
    balance_proof = create_balance_proof(
        channel_identifier,
        C,
        transferred_amount,
        0,
        nonce,
        locksroot,
    )

    with pytest.raises(TransactionFailed):
        token_network.functions.closeChannel(
            channel_identifier,
            B,
            *balance_proof,
        ).transact({'from': A})
Esempio n. 13
0
def test_recover_address_from_cooperative_settle_signature(
        token_network_test_signatures, create_cooperative_settle_signatures,
        get_accounts):
    (A, B) = get_accounts(2)
    other_token_network = token_network_test_signatures
    channel_identifier = 4
    fake_signature = fake_bytes(64)

    (signature_A, signature_B) = create_cooperative_settle_signatures(
        [A, B],
        channel_identifier,
        A,
        0,
        B,
        0,
        other_token_network=other_token_network)
    assert (A == other_token_network.functions.
            recoverAddressFromCooperativeSettleSignaturePublic(
                channel_identifier, A, 0, B, 0, signature_A).call())

    assert (B == other_token_network.functions.
            recoverAddressFromCooperativeSettleSignaturePublic(
                channel_identifier, A, 0, B, 0, signature_B).call())

    assert (B != other_token_network.functions.
            recoverAddressFromCooperativeSettleSignaturePublic(
                channel_identifier, A, 0, B, 0, signature_A).call())

    assert (A != other_token_network.functions.
            recoverAddressFromCooperativeSettleSignaturePublic(
                channel_identifier, A, 0, B, 0, signature_B).call())

    with pytest.raises(TransactionFailed):
        other_token_network.functions.recoverAddressFromCooperativeSettleSignaturePublic(
            channel_identifier, A, 0, B, 0, fake_signature).call()
def test_update_nonexistent_fail(
    get_accounts: Callable,
    token_network: Contract,
    create_balance_proof: Callable,
    create_balance_proof_update_signature: Callable,
) -> None:
    """ updateNonClosingBalanceProof() on a not-yet openned channel should fail """
    (A, B, C) = get_accounts(3)
    channel_identifier = 1

    (settle_block_number, state) = token_network.functions.getChannelInfo(
        channel_identifier, A, B
    ).call()
    assert settle_block_number == 0
    assert state == ChannelState.NONEXISTENT

    balance_proof_A = create_balance_proof(channel_identifier, A, 10, 0, 5, fake_bytes(32, "02"))
    balance_proof_update_signature_B = create_balance_proof_update_signature(
        B, channel_identifier, *balance_proof_A
    )

    with pytest.raises(TransactionFailed):
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier, A, B, *balance_proof_A, balance_proof_update_signature_B
        ).call({"from": C})
def test_close_wrong_signature(
    token_network: Contract,
    create_channel: Callable,
    channel_deposit: Callable,
    get_accounts: Callable,
    create_balance_proof: Callable,
    create_balance_proof_countersignature: Callable,
) -> None:
    """ Closing a channel with a balance proof of the third party should fail """
    (A, B, C) = get_accounts(3)
    deposit_A = 6
    transferred_amount = 5
    nonce = 3
    locksroot = fake_bytes(32, "03")

    channel_identifier = create_channel(A, B)[0]
    channel_deposit(channel_identifier, A, deposit_A, B)

    # Create balance proofs
    balance_proof = create_balance_proof(channel_identifier, C,
                                         transferred_amount, 0, nonce,
                                         locksroot)
    closing_signature_A = create_balance_proof_countersignature(
        A, channel_identifier, MessageTypeId.BALANCE_PROOF, *balance_proof)

    with pytest.raises(TransactionFailed):
        token_network.functions.closeChannel(
            channel_identifier, B, A, *balance_proof,
            closing_signature_A).call({"from": A})
def test_update_notclosed_fail(
        get_accounts,
        token_network,
        create_channel,
        channel_deposit,
        create_balance_proof,
        create_balance_proof_update_signature,
):
    """ updateNonClosingBalanceProof() on an Opened channel should fail """
    (A, B, C) = get_accounts(3)
    channel_identifier = create_channel(A, B)[0]
    channel_deposit(channel_identifier, A, 25, B)

    balance_proof_A = create_balance_proof(channel_identifier, A, 10, 0, 5, fake_bytes(32, '02'))
    balance_proof_update_signature_B = create_balance_proof_update_signature(
        B,
        channel_identifier,
        *balance_proof_A,
    )

    (
        settle_block_number,
        state,
    ) = token_network.functions.getChannelInfo(channel_identifier, A, B).call()
    assert settle_block_number > 0
    assert state == ChannelState.OPENED

    with pytest.raises(TransactionFailed):
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier,
            A,
            B,
            *balance_proof_A,
            balance_proof_update_signature_B,
        ).transact({'from': C})
def test_update_nonexistent_fail(
    get_accounts: Callable,
    token_network: Contract,
    create_balance_proof: Callable,
    create_balance_proof_countersignature: Callable,
) -> None:
    """updateNonClosingBalanceProof() on a not-yet openned channel should fail"""
    (A, B, C) = get_accounts(3)
    channel_identifier = 1

    (settle_block_number,
     state) = token_network.functions.getChannelInfo(channel_identifier, A,
                                                     B).call()
    assert settle_block_number == 0
    assert state == ChannelState.NONEXISTENT

    balance_proof_A = create_balance_proof(channel_identifier, A, 10, 0, 5,
                                           fake_bytes(32, "02"))
    balance_proof_update_signature_B = create_balance_proof_countersignature(
        participant=B,
        channel_identifier=channel_identifier,
        msg_type=MessageTypeId.BALANCE_PROOF_UPDATE,
        **balance_proof_A._asdict(),
    )

    with pytest.raises(TransactionFailed,
                       match="TN/update: channel id mismatch"):
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier,
            A,
            B,
            *balance_proof_A._asdict().values(),
            balance_proof_update_signature_B,
        ).call({"from": C})
def test_update_not_allowed_for_the_closing_address(
    token_network: Contract,
    create_channel: Callable,
    channel_deposit: Callable,
    get_accounts: Callable,
    create_balance_proof: Callable,
    create_balance_proof_countersignature: Callable,
) -> None:
    """ Closing address cannot call updateNonClosingBalanceProof. """
    (A, B, M) = get_accounts(3)
    settle_timeout = TEST_SETTLE_TIMEOUT_MIN
    deposit_A = 20
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, A, deposit_A, B)

    # Some balance proof from B
    balance_proof_B_0 = create_balance_proof(channel_identifier, B, 5, 0, 3, fake_bytes(32, "02"))
    closing_sig_A_0 = create_balance_proof_countersignature(
        A, channel_identifier, MessageTypeId.BALANCE_PROOF, *balance_proof_B_0
    )

    # Later balance proof, higher transferred amount, higher nonce
    balance_proof_B_1 = create_balance_proof(channel_identifier, B, 10, 0, 4, fake_bytes(32, "02"))

    # B's signature on the update message is valid
    balance_proof_update_signature_B = create_balance_proof_countersignature(
        B, channel_identifier, MessageTypeId.BALANCE_PROOF_UPDATE, *balance_proof_B_1
    )

    # A closes with the first balance proof
    token_network.functions.closeChannel(
        channel_identifier, B, A, *balance_proof_B_0, closing_sig_A_0
    ).call_and_transact({"from": A})

    # Someone wants to update with later balance proof - not possible
    with pytest.raises(TransactionFailed):
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier, A, B, *balance_proof_B_1, balance_proof_update_signature_B
        ).call({"from": A})
    with pytest.raises(TransactionFailed):
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier, A, B, *balance_proof_B_1, balance_proof_update_signature_B
        ).call({"from": B})
    with pytest.raises(TransactionFailed):
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier, A, B, *balance_proof_B_1, balance_proof_update_signature_B
        ).call({"from": M})
Esempio n. 19
0
def test_recover_address_from_withdraw_message(
    token_network_test_signatures: Contract,
    create_withdraw_signatures: Callable,
    create_channel_and_deposit: Callable,
    get_accounts: Callable,
) -> None:
    (A, B) = get_accounts(2)
    token_network = token_network_test_signatures
    fake_signature = fake_bytes(64)
    deposit_A = 5
    deposit_B = 7
    withdraw_A = 3
    expiration_block = 492889
    channel_identifier = create_channel_and_deposit(A, B, deposit_A, deposit_B)
    (signature_A, signature_B) = create_withdraw_signatures(
        [A, B],
        channel_identifier,
        A,
        withdraw_A,
        expiration_block,
        token_network.address,
    )

    recovered_address_A = token_network.functions.recoverAddressFromWithdrawMessagePublic(
        channel_identifier, A, withdraw_A, expiration_block,
        signature_A).call()
    assert recovered_address_A == A

    recovered_address_B = token_network.functions.recoverAddressFromWithdrawMessagePublic(
        channel_identifier, A, withdraw_A, expiration_block,
        signature_B).call()
    assert recovered_address_B == B

    with pytest.raises(TransactionFailed):
        token_network.functions.recoverAddressFromWithdrawMessagePublic(
            channel_identifier, A, withdraw_A, expiration_block,
            fake_signature).call()

    wrong_participant = token_network.functions.recoverAddressFromWithdrawMessagePublic(
        channel_identifier, B, withdraw_A, expiration_block,
        signature_A).call()
    assert recovered_address_A != wrong_participant

    wrong_withdraw_value = token_network.functions.recoverAddressFromWithdrawMessagePublic(
        channel_identifier, A, 1, expiration_block, signature_A).call()

    assert recovered_address_A != wrong_withdraw_value

    wrong_signature = token_network.functions.recoverAddressFromWithdrawMessagePublic(
        channel_identifier, A, withdraw_A, expiration_block,
        signature_B).call()

    assert recovered_address_A != wrong_signature

    wrong_expiration = token_network.functions.recoverAddressFromWithdrawMessagePublic(
        channel_identifier, A, withdraw_A, expiration_block + 3,
        signature_B).call()

    assert recovered_address_A != wrong_expiration
Esempio n. 20
0
def test_settle_timeout_inrange(token_network, get_accounts, web3):
    """ The TokenNetwork constructor must enforce that settle timeout is in
    the valid range.

    Also asserts that the constants.py and the netting channel contract values
    are synched.
    """
    (A, B) = get_accounts(2)

    small_settle_timeout = TEST_SETTLE_TIMEOUT_MIN - 1
    large_settle_timeout = TEST_SETTLE_TIMEOUT_MAX + 1

    with pytest.raises(TransactionFailed):
        token_network.functions.openChannel(A, B, small_settle_timeout).call()

    with pytest.raises(TransactionFailed):
        token_network.functions.openChannel(A, B, large_settle_timeout).call()

    token_network.functions.openChannel(
        A, B, TEST_SETTLE_TIMEOUT_MIN).call_and_transact()
    channel_identifier = token_network.functions.getChannelIdentifier(
        A, B).call()
    (settle_block_number,
     _) = token_network.functions.getChannelInfo(channel_identifier, A,
                                                 B).call()

    assert settle_block_number == TEST_SETTLE_TIMEOUT_MIN

    token_network.functions.closeChannel(channel_identifier, B,
                                         fake_bytes(32), 0, fake_bytes(32),
                                         fake_bytes(64)).call_and_transact(
                                             {"from": A})
    web3.testing.mine(TEST_SETTLE_TIMEOUT_MIN + 1)
    token_network.functions.settleChannel(channel_identifier, A, 0, 0,
                                          fake_bytes(32), B, 0, 0,
                                          fake_bytes(32)).call_and_transact(
                                              {"from": A})
    token_network.functions.openChannel(
        A, B, TEST_SETTLE_TIMEOUT_MAX).call_and_transact()
    channel_identifier = token_network.functions.getChannelIdentifier(
        A, B).call()
    (settle_block_number,
     _) = token_network.functions.getChannelInfo(channel_identifier, A,
                                                 B).call()

    assert settle_block_number == TEST_SETTLE_TIMEOUT_MAX
def test_update_allowed_after_settlement_period(
    token_network: Contract,
    create_channel: Callable,
    channel_deposit: Callable,
    get_accounts: Callable,
    create_balance_proof: Callable,
    create_balance_proof_countersignature: Callable,
    web3: Web3,
) -> None:
    """updateNonClosingBalanceProof can be called after the settlement period."""
    (A, B) = get_accounts(2)
    settle_timeout = TEST_SETTLE_TIMEOUT_MIN
    deposit_A = 20
    channel_identifier = create_channel(A, B, settle_timeout)[0]
    channel_deposit(channel_identifier, A, deposit_A, B)
    balance_proof_A = create_balance_proof(channel_identifier, A, 10, 0, 5,
                                           fake_bytes(32, "02"))
    balance_proof_B = create_balance_proof(channel_identifier, B, 5, 0, 3,
                                           fake_bytes(32, "02"))
    closing_sig_A = create_balance_proof_countersignature(
        participant=A,
        channel_identifier=channel_identifier,
        msg_type=MessageTypeId.BALANCE_PROOF,
        **balance_proof_B._asdict(),
    )
    balance_proof_update_signature_B = create_balance_proof_countersignature(
        participant=B,
        channel_identifier=channel_identifier,
        msg_type=MessageTypeId.BALANCE_PROOF_UPDATE,
        **balance_proof_A._asdict(),
    )
    call_and_transact(
        token_network.functions.closeChannel(
            channel_identifier, B, A,
            *balance_proof_B._asdict().values(), closing_sig_A),
        {"from": A},
    )
    mine_blocks(web3, settle_timeout + 1)
    token_network.functions.updateNonClosingBalanceProof(
        channel_identifier,
        A,
        B,
        *balance_proof_A._asdict().values(),
        balance_proof_update_signature_B,
    ).call({"from": A})
Esempio n. 22
0
    def get(
        channel_identifier: int,
        participant1: HexAddress,
        participant1_values: ChannelValues,
        participant2: HexAddress,
        participant2_values: ChannelValues,
    ) -> None:
        nonce1 = 5
        nonce2 = 7
        additional_hash1 = fake_bytes(32)
        additional_hash2 = fake_bytes(32)

        balance_proof_1 = create_balance_proof(
            channel_identifier,
            participant1,
            participant1_values.transferred,
            participant1_values.locked_amounts.locked,
            nonce1,
            participant1_values.locksroot,
            additional_hash1,
        )
        balance_proof_2 = create_balance_proof(
            channel_identifier,
            participant2,
            participant2_values.transferred,
            participant2_values.locked_amounts.locked,
            nonce2,
            participant2_values.locksroot,
            additional_hash2,
        )
        balance_proof_update_signature_2 = create_balance_proof_update_signature(
            participant2, channel_identifier, *balance_proof_1)

        token_network.functions.closeChannel(
            channel_identifier, participant2,
            *balance_proof_2).call_and_transact({"from": participant1})

        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier,
            participant1,
            participant2,
            *balance_proof_1,
            balance_proof_update_signature_2,
        ).call_and_transact({"from": participant2})
def test_update_wrong_signatures(
    token_network,
    create_channel,
    channel_deposit,
    get_accounts,
    create_balance_proof,
    create_balance_proof_update_signature,
):
    """ updateNonClosingBalanceProof() should fail with wrong signatures """
    (A, B, C) = get_accounts(3)
    channel_identifier = create_channel(A, B)[0]
    channel_deposit(channel_identifier, A, 25, B)

    balance_proof_A = create_balance_proof(channel_identifier, A, 10, 0, 5, fake_bytes(32, "02"))
    balance_proof_A_fake = create_balance_proof(
        channel_identifier, A, 10, 0, 5, fake_bytes(32, "02"), signer=C
    )

    balance_proof_update_signature_B = create_balance_proof_update_signature(
        B, channel_identifier, *balance_proof_A
    )
    balance_proof_update_signature_B_fake = create_balance_proof_update_signature(
        C, channel_identifier, *balance_proof_A
    )

    # Close the channel so updateNonClosingBalanceProof() is possible
    token_network.functions.closeChannel(
        channel_identifier, B, EMPTY_BALANCE_HASH, 0, EMPTY_ADDITIONAL_HASH, EMPTY_SIGNATURE
    ).call_and_transact({"from": A})

    with pytest.raises(TransactionFailed):
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier, A, B, *balance_proof_A_fake, balance_proof_update_signature_B
        ).call({"from": C})
    with pytest.raises(TransactionFailed):
        token_network.functions.updateNonClosingBalanceProof(
            channel_identifier, A, B, *balance_proof_A, balance_proof_update_signature_B_fake
        ).call({"from": C})

    # See a success to make sure that the above failures are not spurious
    token_network.functions.updateNonClosingBalanceProof(
        channel_identifier, A, B, *balance_proof_A, balance_proof_update_signature_B
    ).call_and_transact({"from": C})
Esempio n. 24
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)
Esempio n. 25
0
def test_recover_address_from_withdraw_message(
    token_network_test_signatures,
    create_withdraw_signatures,
    create_channel_and_deposit,
    get_accounts,
):
    (A, B) = get_accounts(2)
    token_network = token_network_test_signatures
    fake_signature = fake_bytes(64)
    deposit_A = 5
    deposit_B = 7
    withdraw_A = 3
    channel_identifier = create_channel_and_deposit(A, B, deposit_A, deposit_B)
    (signature_A,
     signature_B) = create_withdraw_signatures([A, B], channel_identifier, A,
                                               withdraw_A,
                                               token_network.address)

    recovered_address_A = token_network.functions.recoverAddressFromWithdrawMessagePublic(
        channel_identifier, A, withdraw_A, signature_A).call()
    assert recovered_address_A == A

    recovered_address_B = token_network.functions.recoverAddressFromWithdrawMessagePublic(
        channel_identifier, A, withdraw_A, signature_B).call()
    assert recovered_address_B == B

    with pytest.raises(TransactionFailed):
        token_network.functions.recoverAddressFromWithdrawMessagePublic(
            channel_identifier, A, withdraw_A, fake_signature).call()

    wrong_participant = token_network.functions.recoverAddressFromWithdrawMessagePublic(
        channel_identifier, B, withdraw_A, signature_A).call()
    assert recovered_address_A != wrong_participant

    wrong_withdraw_value = token_network.functions.recoverAddressFromWithdrawMessagePublic(
        channel_identifier, A, 1, signature_A).call()

    assert recovered_address_A != wrong_withdraw_value

    wrong_signature = token_network.functions.recoverAddressFromWithdrawMessagePublic(
        channel_identifier, A, withdraw_A, signature_B).call()

    assert recovered_address_A != wrong_signature
Esempio n. 26
0
    def get(
        channel_identifier: int,
        participant: HexAddress,
        deposit_participant: int,
        total_withdrawn_participant: int,
        pre_withdrawn_participant: int,
        pre_balance_participant: int,
        partner: HexAddress,
        deposit_partner: HexAddress,
        total_withdrawn_partner: int,
        pre_balance_partner: int,
        pre_balance_contract: int,
        delegate: Optional[HexAddress] = None,
    ) -> None:
        current_withdrawn_participant = total_withdrawn_participant - pre_withdrawn_participant
        (_, state) = token_network.functions.getChannelInfo(
            channel_identifier, participant, partner).call()
        assert state == ChannelState.OPENED

        (
            deposit,
            withdrawn_amount,
            is_the_closer,
            balance_hash,
            nonce,
            locksroot,
            locked_amount,
        ) = token_network.functions.getChannelParticipantInfo(
            channel_identifier, participant, partner).call()
        assert deposit == deposit_participant
        assert withdrawn_amount == total_withdrawn_participant
        assert is_the_closer is False
        assert balance_hash == fake_bytes(32)
        assert nonce == 0
        assert locksroot == NONEXISTENT_LOCKSROOT
        assert locked_amount == 0

        (
            deposit,
            withdrawn_amount,
            is_the_closer,
            balance_hash,
            nonce,
            locksroot,
            locked_amount,
        ) = token_network.functions.getChannelParticipantInfo(
            channel_identifier, partner, participant).call()
        assert deposit == deposit_partner
        assert withdrawn_amount == total_withdrawn_partner
        assert is_the_closer is False
        assert balance_hash == fake_bytes(32)
        assert nonce == 0
        assert locksroot == NONEXISTENT_LOCKSROOT
        assert locked_amount == 0

        balance_participant = custom_token.functions.balanceOf(
            participant).call()
        balance_partner = custom_token.functions.balanceOf(partner).call()
        balance_contract = custom_token.functions.balanceOf(
            token_network.address).call()
        assert balance_participant == pre_balance_participant + current_withdrawn_participant
        assert balance_partner == pre_balance_partner
        assert balance_contract == pre_balance_contract - current_withdrawn_participant

        if delegate is not None:
            balance_delegate = custom_token.functions.balanceOf(
                delegate).call()
            assert balance_delegate == balance_delegate
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_settlement_with_unauthorized_token_transfer(
    web3: Web3,
    get_accounts: Callable,
    custom_token: Contract,
    token_network: Contract,
    assign_tokens: Callable,
    create_channel_and_deposit: Callable,
    withdraw_channel: Callable,
    close_and_update_channel: Callable,
) -> None:
    """A participant transfers some tokens to the contract and so loses them"""
    externally_transferred_amount = 5
    (A, B) = get_accounts(2)
    (vals_A, vals_B) = (
        ChannelValues(deposit=35, withdrawn=10, transferred=0),
        ChannelValues(deposit=40, withdrawn=10, transferred=0),
    )
    vals_A.locksroot = fake_bytes(32, "02")
    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, 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)

    # Assign additional tokens to A
    assign_tokens(A, externally_transferred_amount)
    assert custom_token.functions.balanceOf(
        A).call() >= externally_transferred_amount

    # Fetch onchain balances after settlement
    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 does a transfer to the token_network without appropriate function call - tokens are lost
    call_and_transact(
        custom_token.functions.transfer(token_network.address,
                                        externally_transferred_amount),
        {"from": A},
    )
    assert custom_token.functions.balanceOf(
        token_network.address).call() == (pre_balance_contract +
                                          externally_transferred_amount)

    mine_blocks(web3, TEST_SETTLE_TIMEOUT_MIN + 1)

    # Compute expected settlement amounts
    settlement = get_settlement_amounts(vals_A, vals_B)

    # Channel is settled
    call_settle(token_network, channel_identifier, A, vals_A, B, vals_B)

    # Fetch onchain balances after settlement
    post_balance_A = custom_token.functions.balanceOf(A).call()
    post_balance_B = custom_token.functions.balanceOf(B).call()
    post_balance_contract = custom_token.functions.balanceOf(
        token_network.address).call()

    # A has lost the externally_transferred_amount
    assert (pre_balance_A + settlement.participant1_balance -
            externally_transferred_amount) == post_balance_A

    # B's settlement works correctly
    assert pre_balance_B + settlement.participant2_balance == post_balance_B

    # The externally_transferred_amount stays in the contract
    assert (pre_balance_contract - settlement.participant1_balance -
            settlement.participant2_balance +
            externally_transferred_amount) == post_balance_contract
Esempio n. 29
0
def test_close_channel_state(
    web3,
    custom_token,
    token_network,
    create_channel,
    channel_deposit,
    get_accounts,
    get_block,
    create_balance_proof,
    txn_cost,
):
    """ 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'),
        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,
        vals_B.nonce,
        vals_B.locksroot,
    )

    txn_hash = token_network.functions.closeChannel(
        channel_identifier,
        B,
        *balance_proof_B,
    ).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
Esempio n. 30
0
def test_close_nonce_zero(
    get_accounts,
    token_network,
    create_channel,
    create_balance_proof,
):
    """ 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'),
        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,
        vals_B.nonce,
        vals_B.locksroot,
    )

    (
        _,
        _,
        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

    token_network.functions.closeChannel(
        channel_identifier,
        B,
        *balance_proof_B,
    ).transact({'from': A})

    # 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