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 )
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
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})
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})
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})
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})
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
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})
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})
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_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
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
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
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