def test_settlement_with_unauthorized_token_transfer( web3, get_accounts, custom_token, token_network, create_channel_and_deposit, withdraw_channel, close_and_update_channel, ): externally_transferred_amount = 5 (A, B) = get_accounts(2) (vals_A, vals_B) = ( ChannelValues(deposit=35, withdrawn=10, transferred=0, locked=0), ChannelValues(deposit=40, withdrawn=10, transferred=0, locked=0), ) vals_A.locksroot = fake_bytes(32, '02') vals_B.locksroot = fake_bytes(32, '03') create_channel_and_deposit(A, B, vals_A.deposit, vals_B.deposit) withdraw_channel(A, vals_A.withdrawn, B) withdraw_channel(B, vals_B.withdrawn, A) close_and_update_channel( A, vals_A, B, vals_B, ) # A does a transfer to the token_network without appropriate function call - tokens are lost custom_token.functions.transfer( token_network.address, externally_transferred_amount, ).transact({'from': A}) web3.testing.mine(TEST_SETTLE_TIMEOUT_MIN) # Compute expected settlement amounts settlement = get_settlement_amounts(vals_A, vals_B) # Channel is settled call_settle(token_network, 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 (vals_A.withdrawn + settlement.participant1_balance - externally_transferred_amount == post_balance_A) # B's settlement works correctly assert (settlement.participant2_balance + vals_B.withdrawn == post_balance_B) # The externally_transferred_amount stays in the contract assert (post_balance_contract == externally_transferred_amount)
def test_update_wrong_signatures( token_network, create_channel, channel_deposit, get_accounts, create_balance_proof, create_balance_proof_update_signature, ): (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, ) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, *balance_proof_A_fake, balance_proof_update_signature_B, ).transact({'from': C}) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, *balance_proof_A, balance_proof_update_signature_B_fake, ).transact({'from': C})
def test_register_secret_batch_return_value(secret_registry_contract, get_accounts, get_block): (A, ) = get_accounts(1) secrets = [fake_bytes(32, '02'), fake_bytes(32, '03'), fake_bytes(11)] assert secret_registry_contract.functions.registerSecretBatch( secrets).call() is False secrets[2] = fake_bytes(32, '04') assert secret_registry_contract.functions.registerSecretBatch( secrets).call() is True secret_registry_contract.functions.registerSecret(secrets[1]).transact( {'from': A}) assert secret_registry_contract.functions.registerSecretBatch( secrets).call() is False
def test_close_wrong_signature( token_network, create_channel, channel_deposit, get_accounts, create_balance_proof, ): (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_update_notclosed_fail( get_accounts, token_network, create_channel, channel_deposit, create_balance_proof, create_balance_proof_update_signature, ): (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, token_network, create_balance_proof, create_balance_proof_update_signature, ): (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, ).transact({'from': C})
def test_register_secret_call(secret_registry_contract, event_handler): with pytest.raises(ValidationError): secret_registry_contract.functions.registerSecret().transact() with pytest.raises(ValidationError): secret_registry_contract.functions.registerSecret(3).transact() with pytest.raises(ValidationError): secret_registry_contract.functions.registerSecret(0).transact() with pytest.raises(ValidationError): secret_registry_contract.functions.registerSecret('').transact() with pytest.raises(ValidationError): secret_registry_contract.functions.registerSecret( fake_bytes(33)).transact() assert secret_registry_contract.functions.registerSecret( fake_bytes(32)).call() is False assert secret_registry_contract.functions.registerSecret( fake_bytes(10, '02')).call() is True assert secret_registry_contract.functions.registerSecret( fake_bytes(32, '02')).call() is True
def test_register_secret_batch_events(secret_registry_contract, event_handler): secrets = [ fake_bytes(32, '02'), fake_bytes(32, '03'), fake_bytes(32, '04') ] secret_hashes = [Web3.sha3(secret) for secret in secrets] ev_handler = event_handler(secret_registry_contract) txn_hash = secret_registry_contract.functions.registerSecretBatch( secrets).transact() ev_handler.add( txn_hash, EVENT_SECRET_REVEALED, check_secrets_revealed(secret_hashes, secrets), 3, ) ev_handler.check()
def test_settle_no_bp_success( web3, token_network, create_channel_and_deposit, get_accounts, ): (A, B) = get_accounts(2) deposit_A = 10 deposit_B = 6 settle_timeout = TEST_SETTLE_TIMEOUT_MIN locksroot = fake_bytes(32) additional_hash = fake_bytes(32) channel_identifier = create_channel_and_deposit(A, B, deposit_A, deposit_B) # Close channel with no balance proof token_network.functions.closeChannel( channel_identifier, B, locksroot, 0, additional_hash, fake_bytes(64), ).transact({'from': A}) # Do not call updateNonClosingBalanceProof # Settlement window must be over before settling the channel web3.testing.mine(settle_timeout) # Settling the channel should work with no balance proofs token_network.functions.settleChannel( channel_identifier, A, 0, 0, locksroot, B, 0, 0, locksroot, ).transact({'from': A})
def test_settle_with_locked_but_unregistered( web3, token_network, get_accounts, create_channel_and_deposit, withdraw_channel, close_and_update_channel, custom_token, ): (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=locked_A), ChannelValues(deposit=40, withdrawn=10, transferred=20, locked=0), ) 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) 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, ).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_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, ).transact({'from': A}) web3.testing.mine(settle_timeout) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, *balance_proof_A, balance_proof_update_signature_B, ).transact({'from': A})
def test_register_secret_batch(secret_registry_contract, get_accounts, get_block): (A, ) = get_accounts(1) secrets = [fake_bytes(32, fill) for fill in ('02', '03', '04', '05')] secret_hashes = [Web3.sha3(secret) for secret in secrets] for hash in secret_hashes: assert secret_registry_contract.functions.getSecretRevealBlockHeight( hash).call() == 0 txn_hash = secret_registry_contract.functions.registerSecretBatch( secrets).transact({ 'from': A, }) block = get_block(txn_hash) for hash in secret_hashes: assert secret_registry_contract.functions.getSecretRevealBlockHeight( hash).call() == block
def test_close_channel_state( web3, custom_token, token_network, create_channel, channel_deposit, get_accounts, get_block, create_balance_proof, txn_cost, ): (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) # Create balance proofs balance_proof_B = create_balance_proof( channel_identifier, B, vals_B.transferred, vals_B.locked, vals_B.nonce, vals_B.locksroot, ) ( 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() 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, ): (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
def test_update_wrong_nonce_fail( token_network, create_channel, channel_deposit, get_accounts, create_balance_proof, create_balance_proof_update_signature, update_state_tests, ): (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, ).transact({'from': A}) token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, *balance_proof_A, balance_proof_update_signature_B, ).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, ).transact({'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, ).transact({'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, ).transact({'from': A}) update_state_tests( channel_identifier, A, balance_proof_A, B, balance_proof_B, settle_timeout, txn_hash1, )
def test_settle_channel_state( web3, get_accounts, custom_token, token_network, create_channel_and_deposit, withdraw_channel, close_and_update_channel, settle_state_tests, channel_test_values, ): number_of_channels = 5 accounts = get_accounts(2 * number_of_channels) (vals_A0, vals_B0) = channel_test_values # We mimic old balance proofs here, with a high locked amount and lower transferred amount # We expect to have the same settlement values as the original values def equivalent_transfers(balance_proof): new_balance_proof = deepcopy(balance_proof) new_balance_proof.locked = randint( balance_proof.locked, balance_proof.transferred + balance_proof.locked, ) new_balance_proof.transferred = (balance_proof.transferred + balance_proof.locked - new_balance_proof.locked) return new_balance_proof vals_A_reversed = deepcopy(vals_A0) vals_A_reversed.locked = vals_A0.transferred vals_A_reversed.transferred = vals_A0.locked vals_B_reversed = deepcopy(vals_B0) vals_B_reversed.locked = vals_B0.transferred vals_B_reversed.transferred = vals_B0.locked new_values = [ (vals_A0, vals_B0), (vals_A_reversed, vals_B_reversed), ] + [ sorted( [ equivalent_transfers(vals_A0), equivalent_transfers(vals_B0), ], key=lambda x: x.transferred + x.locked, reverse=False, ) for no in range(0, number_of_channels - 1) ] # Calculate how much A and B should receive settlement = get_settlement_amounts(vals_A0, vals_B0) # Calculate how much A and B receive according to onchain computation settlement2 = get_onchain_settlement_amounts(vals_A0, vals_B0) for no in range(0, number_of_channels + 1): A = accounts[no] B = accounts[no + 1] (vals_A, vals_B) = new_values[no] vals_A.locksroot = fake_bytes(32, '02') vals_B.locksroot = fake_bytes(32, '03') create_channel_and_deposit(A, B, vals_A.deposit, vals_B.deposit) withdraw_channel(A, vals_A.withdrawn, B) withdraw_channel(B, vals_B.withdrawn, A) close_and_update_channel( A, vals_A, B, vals_B, ) web3.testing.mine(SETTLE_TIMEOUT_MIN) pre_balance_A = custom_token.functions.balanceOf(A).call() pre_balance_B = custom_token.functions.balanceOf(B).call() pre_balance_contract = custom_token.functions.balanceOf( token_network.address).call() call_settle(token_network, A, vals_A, B, vals_B) # We do the balance & state tests here for each channel and also compare with # the expected settlement amounts settle_state_tests( A, vals_A, B, vals_B, pre_balance_A, pre_balance_B, pre_balance_contract, ) # We compute again the settlement amounts here to compare with the other channel # settlement test values, which should be equal # Calculate how much A and B should receive settlement_equivalent = get_settlement_amounts(vals_A, vals_B) assert (settlement.participant1_balance + settlement.participant2_locked == settlement_equivalent.participant1_balance + settlement_equivalent.participant2_locked) assert (settlement.participant2_balance + settlement.participant1_locked == settlement_equivalent.participant2_balance + settlement_equivalent.participant1_locked) # Calculate how much A and B receive according to onchain computation settlement2_equivalent = get_onchain_settlement_amounts(vals_A, vals_B) assert (settlement2.participant1_balance + settlement2.participant2_locked == settlement2_equivalent.participant1_balance + settlement2_equivalent.participant2_locked) assert (settlement2.participant2_balance + settlement2.participant1_locked == settlement2_equivalent.participant2_balance + settlement2_equivalent.participant1_locked)
def test_settle_single_direct_transfer_for_counterparty( web3, get_accounts, custom_token, token_network, create_channel, channel_deposit, create_balance_proof, create_balance_proof_update_signature, ): """ Test settle of a channel with one direct transfer to the participant that did not call close. """ (A, B) = get_accounts(2) (vals_A, vals_B) = ( ChannelValues(deposit=10, withdrawn=0, transferred=5, locked=0), ChannelValues(deposit=1, withdrawn=0, transferred=0, locked=0), ) settle_timeout = TEST_SETTLE_TIMEOUT_MIN locksroot = fake_bytes(32) additional_hash = fake_bytes(32) channel_identifier = create_channel(A, B)[0] channel_deposit(channel_identifier, A, vals_A.deposit, B) channel_deposit(channel_identifier, B, vals_B.deposit, A) token_network.functions.closeChannel( channel_identifier, B, locksroot, 0, additional_hash, fake_bytes(64), ).transact({'from': A}) balance_proof_A = create_balance_proof(channel_identifier, A, vals_A.transferred, vals_A.locked, 1, locksroot) balance_proof_update_signature_B = create_balance_proof_update_signature( B, channel_identifier, *balance_proof_A, ) token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, *balance_proof_A, balance_proof_update_signature_B, ).transact({'from': B}) pre_balance_A = custom_token.functions.balanceOf(A).call() pre_balance_B = custom_token.functions.balanceOf(B).call() pre_balance_contract = custom_token.functions.balanceOf( token_network.address).call() web3.testing.mine(settle_timeout) token_network.functions.settleChannel( channel_identifier, B, 0, 0, locksroot, A, vals_A.transferred, 0, locksroot, ).transact({'from': B}) # Calculate how much A and B should receive expected_settlement = get_settlement_amounts(vals_B, vals_A) # Calculate how much A and B receive according to onchain computation onchain_settlement = get_onchain_settlement_amounts(vals_B, vals_A) assert (expected_settlement.participant1_balance == onchain_settlement.participant1_balance) assert (expected_settlement.participant2_balance == onchain_settlement.participant2_balance) assert custom_token.functions.balanceOf(A).call() == pre_balance_A + 5 assert custom_token.functions.balanceOf(B).call() == pre_balance_B + 6 assert custom_token.functions.balanceOf( token_network.address, ).call() == pre_balance_contract - 11
def test_update_call( get_accounts, token_network, create_channel, channel_deposit, create_balance_proof, create_balance_proof_update_signature, ): (A, B, C) = get_accounts(3) channel_identifier = create_channel(A, B)[0] channel_deposit(channel_identifier, A, 15, B) token_network.functions.closeChannel( channel_identifier, B, EMPTY_BALANCE_HASH, 0, EMPTY_ADDITIONAL_HASH, EMPTY_SIGNATURE, ).transact({'from': A}) 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, ) (balance_hash, nonce, additional_hash, closing_signature) = balance_proof_A with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, EMPTY_ADDRESS, B, *balance_proof_A, balance_proof_update_signature_B, ).transact({'from': C}) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, EMPTY_ADDRESS, *balance_proof_A, balance_proof_update_signature_B, ).transact({'from': C}) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, *balance_proof_A, EMPTY_SIGNATURE, ).transact({'from': C}) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, EMPTY_BALANCE_HASH, nonce, additional_hash, closing_signature, balance_proof_update_signature_B, ).transact({'from': C}) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, balance_hash, 0, additional_hash, closing_signature, balance_proof_update_signature_B, ).transact({'from': C}) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, balance_hash, nonce, additional_hash, EMPTY_SIGNATURE, balance_proof_update_signature_B, ).transact({'from': C})
def test_settle_wrong_balance_hash( web3, get_accounts, token_network, create_channel_and_deposit, close_and_update_channel, get_block, reveal_secrets, ): (A, B) = get_accounts(2) vals_A = ChannelValues( deposit=35, withdrawn=0, transferred=5, claimable_locked=10, unclaimable_locked=2, ) vals_B = ChannelValues( deposit=40, withdrawn=0, transferred=15, 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( web3, unlockable_amount=vals_A.claimable_locked, expired_amount=vals_A.unclaimable_locked, ) vals_A.locksroot = pending_transfers_tree_A.merkle_root # 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( web3, unlockable_amount=vals_B.claimable_locked, expired_amount=vals_B.unclaimable_locked, ) vals_B.locksroot = pending_transfers_tree_B.merkle_root # Reveal B's secrets reveal_secrets(B, pending_transfers_tree_B.unlockable) close_and_update_channel( channel_identifier, A, vals_A, B, vals_B, ) web3.testing.mine(TEST_SETTLE_TIMEOUT_MIN) 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 = MAX_UINT256 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 += 1 with pytest.raises(TransactionFailed): call_settle(token_network, channel_identifier, A, vals_A_fail, B, vals_B) vals_A_fail.locked = 0 with pytest.raises(TransactionFailed): call_settle(token_network, channel_identifier, A, vals_A_fail, B, vals_B) vals_A_fail.locked = MAX_UINT256 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 = EMPTY_LOCKSROOT 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 = MAX_UINT256 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 += 1 with pytest.raises(TransactionFailed): call_settle(token_network, channel_identifier, A, vals_A, B, vals_B_fail) vals_B_fail.locked = 0 with pytest.raises(TransactionFailed): call_settle(token_network, channel_identifier, B, vals_B_fail, A, vals_A) vals_B_fail.locked = MAX_UINT256 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 = EMPTY_LOCKSROOT 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_update_channel_state( web3, custom_token, token_network, create_channel, channel_deposit, get_accounts, create_balance_proof, create_balance_proof_update_signature, update_state_tests, txn_cost, ): (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, ).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, ).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_update_signature_on_invalid_arguments( token_network, token_network_test_utils, create_channel, channel_deposit, get_accounts, create_balance_proof, create_balance_proof_update_signature, ): """ Call updateNonClosingBalanceProof with signature on invalid argument fails. """ (A, B, C) = 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) balance_proof = namedtuple( 'balance_proof', ['balance_hash', 'nonce', 'additional_hash', 'signature'], ) # Close channel token_network.functions.closeChannel( channel_identifier, B, EMPTY_BALANCE_HASH, 0, EMPTY_ADDITIONAL_HASH, EMPTY_SIGNATURE, ).transact({'from': A}) # Create valid balance_proof balance_proof_valid = balance_proof(*create_balance_proof( channel_identifier, A, 10, 0, 2, fake_bytes(32, '02'), fake_bytes(32, '02'), )) signature_invalid_token_network_address = create_balance_proof_update_signature( B, channel_identifier, *balance_proof_valid, other_token_network=token_network_test_utils, # invalid token_network_address ) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, *balance_proof_valid, signature_invalid_token_network_address, ).transact({'from': B}) signature_invalid_participant = create_balance_proof_update_signature( C, # invalid signer channel_identifier, balance_proof_valid.balance_hash, balance_proof_valid.nonce, balance_proof_valid.additional_hash, balance_proof_valid.signature, ) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, *balance_proof_valid, signature_invalid_participant, ).transact({'from': B}) signature_invalid_channel_identifier = create_balance_proof_update_signature( B, channel_identifier + 1, # invalid channel_identifier balance_proof_valid.balance_hash, balance_proof_valid.nonce, balance_proof_valid.additional_hash, balance_proof_valid.signature, ) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, *balance_proof_valid, signature_invalid_channel_identifier, ).transact({'from': B}) signature_invalid_balance_hash = create_balance_proof_update_signature( B, channel_identifier, balance_proof_valid.balance_hash[::-1], # invalid balance_hash balance_proof_valid.nonce, balance_proof_valid.additional_hash, balance_proof_valid.signature, ) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, *balance_proof_valid, signature_invalid_balance_hash, ).transact({'from': B}) signature_invalid_nonce = create_balance_proof_update_signature( B, channel_identifier, balance_proof_valid.balance_hash, 1, # invalid nonce balance_proof_valid.additional_hash, balance_proof_valid.signature, ) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, *balance_proof_valid, signature_invalid_nonce, ).transact({'from': B}) signature_invalid_additional_hash = create_balance_proof_update_signature( B, channel_identifier, balance_proof_valid.balance_hash, balance_proof_valid.nonce, b'\x00' * 32, # invalid additional_hash balance_proof_valid.signature, ) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, *balance_proof_valid, signature_invalid_additional_hash, ).transact({'from': B}) signature_invalid_closing_signature = create_balance_proof_update_signature( B, channel_identifier, balance_proof_valid.balance_hash, balance_proof_valid.nonce, balance_proof_valid.additional_hash, balance_proof_valid.signature[::-1], ) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, *balance_proof_valid, signature_invalid_closing_signature, ).transact({'from': B}) # Call with same balance_proof and signature on valid arguments works balance_proof_update_signature = create_balance_proof_update_signature( B, channel_identifier, *balance_proof_valid, ) token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, *balance_proof_valid, balance_proof_update_signature, ).transact({'from': B})
def test_update_invalid_balance_proof_arguments( token_network, token_network_test_utils, create_channel, channel_deposit, get_accounts, create_balance_proof, create_balance_proof_update_signature, ): (A, B, C) = 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) token_network.functions.closeChannel( channel_identifier, B, EMPTY_BALANCE_HASH, 0, EMPTY_ADDITIONAL_HASH, EMPTY_SIGNATURE, ).transact({'from': A}) balance_proof = namedtuple( 'balance_proof', ['balance_hash', 'nonce', 'additional_hash', 'signature'], ) # Create valid balance_proof balance_proof_valid = balance_proof(*create_balance_proof( channel_identifier, A, 10, 0, 2, fake_bytes(32, '02'), )) # And a valid nonclosing_signature valid_balance_proof_update_signature = create_balance_proof_update_signature( B, channel_identifier, *balance_proof_valid, ) # We test invalid balance proof arguments with valid signatures # Create balance_proof for invalid token_network balance_proof_invalid_token_network = balance_proof(*create_balance_proof( channel_identifier, A, 10, 0, 2, fake_bytes(32, '02'), other_token_network=token_network_test_utils, )) signature_invalid_token_network = create_balance_proof_update_signature( B, channel_identifier, balance_proof_valid.balance_hash, balance_proof_valid.nonce, balance_proof_valid.additional_hash, balance_proof_valid.signature, other_token_network=token_network_test_utils, ) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, *balance_proof_invalid_token_network, signature_invalid_token_network, ).transact({'from': B}) # Create balance_proof for invalid channel participant balance_proof_invalid_channel_participant = balance_proof(*create_balance_proof( channel_identifier, C, 10, 0, 2, fake_bytes(32, '02'), )) signature_invalid_channel_participant = create_balance_proof_update_signature( B, channel_identifier, balance_proof_valid.balance_hash, balance_proof_valid.nonce, balance_proof_valid.additional_hash, balance_proof_valid.signature, ) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, *balance_proof_invalid_channel_participant, signature_invalid_channel_participant, ).transact({'from': B}) # Create balance_proof for invalid channel identifier balance_proof_invalid_channel_identifier = balance_proof(*create_balance_proof( channel_identifier + 1, A, 10, 0, 2, fake_bytes(32, '02'), )) signature_invalid_channel_identifier = create_balance_proof_update_signature( B, channel_identifier + 1, balance_proof_valid.balance_hash, balance_proof_valid.nonce, balance_proof_valid.additional_hash, balance_proof_valid.signature, ) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, *balance_proof_invalid_channel_identifier, signature_invalid_channel_identifier, ).transact({'from': B}) signature_invalid_balance_hash = create_balance_proof_update_signature( B, channel_identifier, balance_proof_valid.balance_hash[::-1], balance_proof_valid.nonce, balance_proof_valid.additional_hash, balance_proof_valid.signature, ) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, balance_proof_valid.balance_hash[::-1], # invalid balance_hash balance_proof_valid.nonce, balance_proof_valid.additional_hash, balance_proof_valid.signature, signature_invalid_balance_hash, ).transact({'from': B}) signature_invalid_nonce = create_balance_proof_update_signature( B, channel_identifier, balance_proof_valid.balance_hash, 1, balance_proof_valid.additional_hash, balance_proof_valid.signature, ) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, balance_proof_valid.balance_hash, 1, # invalid nonce balance_proof_valid.additional_hash, balance_proof_valid.signature, signature_invalid_nonce, ).transact({'from': B}) signature_invalid_additional_hash = create_balance_proof_update_signature( B, channel_identifier, balance_proof_valid.balance_hash, balance_proof_valid.nonce, balance_proof_valid.additional_hash[::-1], balance_proof_valid.signature, ) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, balance_proof_valid.balance_hash, balance_proof_valid.nonce, fake_bytes(32, '02'), # invalid additional_hash balance_proof_valid.signature, signature_invalid_additional_hash, ).transact({'from': B}) signature_invalid_closing_signature = create_balance_proof_update_signature( B, channel_identifier, balance_proof_valid.balance_hash, balance_proof_valid.nonce, balance_proof_valid.additional_hash, balance_proof_valid.signature[::-1], ) with pytest.raises(TransactionFailed): token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, balance_proof_valid.balance_hash, balance_proof_valid.nonce, balance_proof_valid.additional_hash, balance_proof_valid.signature, signature_invalid_closing_signature[::-1], # invalid non-closing signature ).transact({'from': B}) # Call with same balance_proof and signature on valid arguments still works token_network.functions.updateNonClosingBalanceProof( channel_identifier, A, B, *balance_proof_valid, valid_balance_proof_update_signature, ).transact({'from': B})
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})