def test_direct_transfer(raiden_network, token_addresses, deposit, network_wait): token_address = token_addresses[0] app0, app1 = raiden_network amount = 10 chain_state = views.state_from_app(app0) payment_network_id = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( chain_state, payment_network_id, token_address, ) direct_transfer( app0, app1, token_network_identifier, amount, timeout=network_wait, ) assert_synched_channel_state( token_network_identifier, app0, deposit - amount, [], app1, deposit + amount, [], )
def test_failsfast_lockedtransfer_exceeding_distributable( raiden_network, token_addresses, deposit, ): app0, app1 = raiden_network token_address = token_addresses[0] payment_network_identifier = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), payment_network_identifier, token_address, ) result = app0.raiden.mediated_transfer_async( token_network_identifier, deposit * 2, app1.raiden.address, identifier=1, ) assert result.successful() assert result.get_nowait() is False assert_synched_channel_state( token_network_identifier, app0, deposit, [], app1, deposit, [], )
def test_receive_directtransfer_invalidnonce(raiden_network, deposit, token_addresses): app0, app1 = raiden_network token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) channel0 = get_channelstate(app0, app1, token_network_identifier) transferred_amount = 10 same_payment_identifier = 1 message_identifier = random.randint(0, UINT64_MAX) event = channel.send_directtransfer( channel0, transferred_amount, message_identifier, same_payment_identifier, ) direct_transfer_message = DirectTransfer.from_event(event) sign_and_inject( direct_transfer_message, app0.raiden.private_key, app0.raiden.address, app1, ) # Send a *different* direct transfer with the *same nonce* invalid_transferred_amount = transferred_amount // 2 message_identifier = random.randint(0, UINT64_MAX) invalid_direct_transfer_message = DirectTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=message_identifier, payment_identifier=same_payment_identifier, nonce=1, token_network_address=token_network_identifier, token=token_address, channel_identifier=channel0.identifier, transferred_amount=invalid_transferred_amount, locked_amount=0, recipient=app1.raiden.address, locksroot=EMPTY_MERKLE_ROOT, ) sign_and_inject( invalid_direct_transfer_message, app0.raiden.private_key, app0.raiden.address, app1, ) assert_synched_channel_state( token_network_identifier, app0, deposit - transferred_amount, [], app1, deposit + transferred_amount, [], )
def test_settle_is_automatically_called(raiden_network, token_addresses, deposit): """Settle is automatically called by one of the nodes.""" app0, app1 = raiden_network registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) channel_identifier = get_channelstate(app0, app1, token_network_identifier).identifier # A ChannelClose event will be generated, this will be polled by both apps # and each must start a task for calling settle RaidenAPI(app1.raiden).channel_close( registry_address, token_address, app0.raiden.address, ) waiting.wait_for_settle( app0.raiden, registry_address, token_address, [channel_identifier], app0.raiden.alarm.sleep_time, ) assert_synched_channel_state( token_network_identifier, app0, deposit, [], app1, deposit, [], ) state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier( from_identifier=0, to_identifier='latest', ) channel_state = get_channelstate(app0, app1, token_network_identifier) assert channel_state.close_transaction.finished_block_number assert channel_state.settle_transaction.finished_block_number assert must_contain_entry(state_changes, ContractReceiveChannelClosed, { 'token_network_identifier': token_network_identifier, 'channel_identifier': channel_identifier, 'closing_address': app1.raiden.address, 'closed_block_number': channel_state.close_transaction.finished_block_number, }) assert must_contain_entry(state_changes, ContractReceiveChannelSettled, { 'token_network_identifier': token_network_identifier, 'channel_identifier': channel_identifier, 'settle_block_number': channel_state.settle_transaction.finished_block_number, })
def test_refund_messages(raiden_chain, token_addresses, deposit): # The network has the following topology: # # App0 <---> App1 <---> App2 app0, app1, app2 = raiden_chain # pylint: disable=unbalanced-tuple-unpacking token_address = token_addresses[0] payment_network_identifier = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), payment_network_identifier, token_address, ) # Exhaust the channel App1 <-> App2 (to force the refund transfer) exhaust_amount = deposit direct_transfer(app1, app2, token_network_identifier, exhaust_amount, identifier=1) refund_amount = deposit // 2 identifier = 1 async_result = app0.raiden.mediated_transfer_async( token_network_identifier, refund_amount, app2.raiden.address, identifier, ) assert async_result.wait() is False, 'Must fail, there are no routes available' # The transfer from app0 to app2 failed, so the balances did change. # Since the refund is not unlocked both channels have the corresponding # amount locked (issue #1091) send_lockedtransfer = raiden_events_must_contain_entry( app0.raiden, SendLockedTransfer, {'transfer': {'lock': {'amount': refund_amount}}}, ) assert send_lockedtransfer send_refundtransfer = raiden_events_must_contain_entry(app1.raiden, SendRefundTransfer, {}) assert send_refundtransfer assert_synched_channel_state( token_network_identifier, app0, deposit, [send_lockedtransfer.transfer.lock], app1, deposit, [send_refundtransfer.lock], ) # This channel was exhausted to force the refund transfer assert_synched_channel_state( token_network_identifier, app1, 0, [], app2, deposit * 2, [], )
def test_received_directtransfer_closedchannel(raiden_network, token_addresses, deposit): app0, app1 = raiden_network token_address = token_addresses[0] registry_address = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), registry_address, token_address, ) channel0 = get_channelstate(app0, app1, token_network_identifier) RaidenAPI(app1.raiden).channel_close( registry_address, token_address, app0.raiden.address, ) wait_until_block( app0.raiden.chain, app0.raiden.chain.block_number() + 1, ) # Now receive one direct transfer for the closed channel message_identifier = random.randint(0, UINT64_MAX) direct_transfer_message = DirectTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=message_identifier, payment_identifier=1, nonce=1, token_network_address=token_network_identifier, token=token_address, channel_identifier=channel0.identifier, transferred_amount=10, locked_amount=0, recipient=app0.raiden.address, locksroot=EMPTY_MERKLE_ROOT, ) sign_and_inject( direct_transfer_message, app0.raiden.private_key, app0.raiden.address, app1, ) # The local state must not change since the channel is already closed assert_synched_channel_state( token_network_identifier, app0, deposit, [], app1, deposit, [], )
def test_receive_lockedtransfer_invalidrecipient( raiden_network, token_addresses, reveal_timeout, deposit, ): app0, app1 = raiden_network token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) channel0 = get_channelstate(app0, app1, token_network_identifier) payment_identifier = 1 invalid_recipient = make_address() lock_amount = 10 expiration = reveal_timeout * 2 mediated_transfer_message = LockedTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=random.randint(0, UINT64_MAX), payment_identifier=payment_identifier, nonce=1, token_network_address=token_network_identifier, token=token_address, channel_identifier=channel0.identifier, transferred_amount=0, locked_amount=lock_amount, recipient=invalid_recipient, locksroot=UNIT_SECRETHASH, lock=Lock(lock_amount, expiration, UNIT_SECRETHASH), target=app1.raiden.address, initiator=app0.raiden.address, fee=0, ) sign_and_inject( mediated_transfer_message, app0.raiden.private_key, app0.raiden.address, app1, ) assert_synched_channel_state( token_network_identifier, app0, deposit, [], app1, deposit, [], )
def test_receive_directtransfer_invalidlocksroot(raiden_network, token_addresses): app0, app1 = raiden_network token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) channel0 = get_channelstate(app0, app1, token_network_identifier) balance0 = channel.get_balance(channel0.our_state, channel0.partner_state) balance1 = channel.get_balance(channel0.partner_state, channel0.our_state) payment_identifier = 1 invalid_locksroot = UNIT_SECRETHASH channel_identifier = channel0.identifier message_identifier = random.randint(0, UINT64_MAX) direct_transfer_message = DirectTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=message_identifier, payment_identifier=payment_identifier, nonce=1, token_network_address=token_network_identifier, token=token_address, channel_identifier=channel_identifier, transferred_amount=0, locked_amount=0, recipient=app1.raiden.address, locksroot=invalid_locksroot, ) sign_and_inject( direct_transfer_message, app0.raiden.private_key, app0.raiden.address, app1, ) assert_synched_channel_state( token_network_identifier, app0, balance0, [], app1, balance1, [], )
def test_receive_directtransfer_invalidtoken(raiden_network, deposit, token_addresses): app0, app1 = raiden_network token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) channel0 = get_channelstate(app0, app1, token_network_identifier) message_identifier = random.randint(0, UINT64_MAX) payment_identifier = 1 invalid_token_address = make_address() channel_identifier = channel0.identifier direct_transfer_message = DirectTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=message_identifier, payment_identifier=payment_identifier, nonce=1, token_network_address=token_network_identifier, token=invalid_token_address, channel_identifier=channel_identifier, transferred_amount=0, locked_amount=0, recipient=app1.raiden.address, locksroot=EMPTY_MERKLE_ROOT, ) sign_and_inject( direct_transfer_message, app0.raiden.private_key, app0.raiden.address, app1, ) assert_synched_channel_state( token_network_identifier, app0, deposit, [], app1, deposit, [], )
def test_direct_transfer_to_offline_node(raiden_network, token_addresses, deposit): app0, app1 = raiden_network token_address = token_addresses[0] chain_state = views.state_from_app(app0) payment_network_id = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( chain_state, payment_network_id, token_address, ) # Wait until the initialization of the node is complete and then stop it gevent.wait([app1.raiden.start_event]) app1.raiden.stop() amount = 10 target = app1.raiden.address payment_identifier = 13 app0.raiden.direct_transfer_async( token_network_identifier, amount, target, identifier=payment_identifier, ) app1.raiden.start() exception = ValueError('Waiting for transfer received success in the WAL timed out') with gevent.Timeout(seconds=5, exception=exception): wait_for_transfer_success( app1.raiden, payment_identifier, amount, app1.raiden.alarm.sleep_time, ) no_outstanding_locks = [] assert_synched_channel_state( token_network_identifier, app0, deposit - amount, no_outstanding_locks, app1, deposit + amount, no_outstanding_locks, )
def test_refund_messages(raiden_chain, token_addresses, deposit): # The network has the following topology: # # App0 <---> App1 <---> App2 app0, app1, app2 = raiden_chain # pylint: disable=unbalanced-tuple-unpacking token_address = token_addresses[0] payment_network_identifier = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), payment_network_identifier, token_address, ) # Exhaust the channel App1 <-> App2 (to force the refund transfer) exhaust_amount = deposit direct_transfer(app1, app2, token_network_identifier, exhaust_amount, identifier=1) refund_amount = deposit // 2 identifier = 1 async_result = app0.raiden.mediated_transfer_async( token_network_identifier, refund_amount, app2.raiden.address, identifier, ) assert async_result.wait( ) is False, 'Must fail, there are no routes available' # The transfer from app0 to app2 failed, so the balances did change. # Since the refund is not unlocked both channels have the corresponding # amount locked (issue #1091) send_lockedtransfer = raiden_events_must_contain_entry( app0.raiden, SendLockedTransfer, {'transfer': { 'lock': { 'amount': refund_amount } }}, ) assert send_lockedtransfer send_refundtransfer = raiden_events_must_contain_entry( app1.raiden, SendRefundTransfer, {}) assert send_refundtransfer assert_synched_channel_state( token_network_identifier, app0, deposit, [send_lockedtransfer.transfer.lock], app1, deposit, [send_refundtransfer.lock], ) # This channel was exhausted to force the refund transfer assert_synched_channel_state( token_network_identifier, app1, 0, [], app2, deposit * 2, [], )
def test_recovery_happy_case( raiden_network, number_of_nodes, deposit, token_addresses, network_wait, skip_if_not_udp, ): app0, app1, app2 = raiden_network token_address = token_addresses[0] chain_state = views.state_from_app(app0) payment_network_id = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( chain_state, payment_network_id, token_address, ) # make a few transfers from app0 to app2 amount = 1 spent_amount = deposit - 2 for _ in range(spent_amount): mediated_transfer( app0, app2, token_network_identifier, amount, timeout=network_wait * number_of_nodes, ) app0.raiden.stop() host_port = (app0.raiden.config['host'], app0.raiden.config['port']) socket = server._udp_socket(host_port) new_transport = UDPTransport( app0.discovery, socket, app0.raiden.transport.throttle_policy, app0.raiden.config['transport'], ) app0_restart = App( config=app0.config, chain=app0.raiden.chain, query_start_block=0, default_registry=app0.raiden.default_registry, default_secret_registry=app0.raiden.default_secret_registry, transport=new_transport, discovery=app0.raiden.discovery, ) app0.stop() del app0 # from here on the app0_restart should be used assert_synched_channel_state( token_network_identifier, app0_restart, deposit - spent_amount, [], app1, deposit + spent_amount, [], ) assert_synched_channel_state( token_network_identifier, app1, deposit - spent_amount, [], app2, deposit + spent_amount, [], ) # wait for the nodes' healthcheck to update the network statuses waiting.wait_for_healthy( app0_restart.raiden, app1.raiden.address, network_wait, ) waiting.wait_for_healthy( app1.raiden, app0_restart.raiden.address, network_wait, ) mediated_transfer( app2, app0_restart, token_network_identifier, amount, timeout=network_wait * number_of_nodes * 2, ) mediated_transfer( app0_restart, app2, token_network_identifier, amount, timeout=network_wait * number_of_nodes * 2, ) assert_synched_channel_state( token_network_identifier, app0_restart, deposit - spent_amount, [], app1, deposit + spent_amount, [], ) assert_synched_channel_state( token_network_identifier, app1, deposit - spent_amount, [], app2, deposit + spent_amount, [], )
def test_refund_transfer(raiden_chain, number_of_nodes, token_addresses, deposit, network_wait): """A failed transfer must send a refund back. TODO: - Unlock the token on refund #1091 - Clear the merkletree and update the locked amount #193 - Remove the refund message type #490""" # Topology: # # 0 -> 1 -> 2 # app0, app1, app2 = raiden_chain token_address = token_addresses[0] payment_network_identifier = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), payment_network_identifier, token_address, ) # make a transfer to test the path app0 -> app1 -> app2 identifier_path = 1 amount_path = 1 mediated_transfer( app0, app2, token_network_identifier, amount_path, identifier_path, timeout=network_wait * number_of_nodes, ) # drain the channel app1 -> app2 identifier_drain = 2 amount_drain = deposit * 8 // 10 direct_transfer( app1, app2, token_network_identifier, amount_drain, identifier_drain, timeout=network_wait, ) # wait for the nodes to sync gevent.sleep(0.2) assert_synched_channel_state( token_network_identifier, app0, deposit - amount_path, [], app1, deposit + amount_path, [], ) assert_synched_channel_state( token_network_identifier, app1, deposit - amount_path - amount_drain, [], app2, deposit + amount_path + amount_drain, [], ) # app0 -> app1 -> app2 is the only available path, but the channel app1 -> # app2 doesn't have capacity, so a refund will be sent on app1 -> app0 identifier_refund = 3 amount_refund = 50 async_result = app0.raiden.mediated_transfer_async( token_network_identifier, amount_refund, app2.raiden.address, identifier_refund, ) assert async_result.wait( ) is False, 'there is no path with capacity, the transfer must fail' gevent.sleep(0.2) # A lock structure with the correct amount send_locked = raiden_events_must_contain_entry( app0.raiden, SendLockedTransfer, {'transfer': { 'lock': { 'amount': amount_refund } }}, ) assert send_locked send_refund = raiden_events_must_contain_entry(app1.raiden, SendRefundTransfer, {}) assert send_refund lock = send_locked.transfer.lock refund_lock = send_refund.lock assert lock.amount == refund_lock.amount assert lock.secrethash assert lock.expiration # Both channels have the amount locked because of the refund message assert_synched_channel_state( token_network_identifier, app0, deposit - amount_path, [lockstate_from_lock(lock)], app1, deposit + amount_path, [lockstate_from_lock(refund_lock)], ) assert_synched_channel_state( token_network_identifier, app1, deposit - amount_path - amount_drain, [], app2, deposit + amount_path + amount_drain, [], )
def test_refund_transfer_after_2nd_hop( raiden_chain, number_of_nodes, token_addresses, deposit, network_wait, ): """Test the refund transfer sent due to failure after 2nd hop""" # Topology: # # 0 -> 1 -> 2 -> 3 # app0, app1, app2, app3 = raiden_chain token_address = token_addresses[0] payment_network_identifier = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), payment_network_identifier, token_address, ) # make a transfer to test the path app0 -> app1 -> app2 -> app3 identifier_path = 1 amount_path = 1 mediated_transfer( app0, app3, token_network_identifier, amount_path, identifier_path, timeout=network_wait * number_of_nodes, ) # drain the channel app2 -> app3 identifier_drain = 2 amount_drain = deposit * 8 // 10 direct_transfer( app2, app3, token_network_identifier, amount_drain, identifier_drain, timeout=network_wait, ) # wait for the nodes to sync gevent.sleep(0.2) assert_synched_channel_state( token_network_identifier, app0, deposit - amount_path, [], app1, deposit + amount_path, [], ) assert_synched_channel_state( token_network_identifier, app1, deposit - amount_path, [], app2, deposit + amount_path, [], ) assert_synched_channel_state( token_network_identifier, app2, deposit - amount_path - amount_drain, [], app3, deposit + amount_path + amount_drain, [], ) # app0 -> app1 -> app2 > app3 is the only available path, but the channel # app2 -> app3 doesn't have capacity, so a refund will be sent on # app2 -> app1 -> app0 identifier_refund = 3 amount_refund = 50 async_result = app0.raiden.mediated_transfer_async( token_network_identifier, amount_refund, app3.raiden.address, identifier_refund, ) assert async_result.wait( ) is False, 'there is no path with capacity, the transfer must fail' gevent.sleep(0.2) # Lock structures with the correct amount send_locked1 = raiden_events_must_contain_entry( app0.raiden, SendLockedTransfer, {'transfer': { 'lock': { 'amount': amount_refund } }}, ) assert send_locked1 send_refund1 = raiden_events_must_contain_entry(app1.raiden, SendRefundTransfer, {}) assert send_refund1 lock1 = send_locked1.transfer.lock refund_lock1 = send_refund1.lock assert lock1.amount == refund_lock1.amount assert lock1.secrethash == refund_lock1.secrethash send_locked2 = raiden_events_must_contain_entry( app1.raiden, SendLockedTransfer, {'transfer': { 'lock': { 'amount': amount_refund } }}, ) assert send_locked2 send_refund2 = raiden_events_must_contain_entry(app2.raiden, SendRefundTransfer, {}) assert send_refund2 lock2 = send_locked2.transfer.lock refund_lock2 = send_refund2.lock assert lock2.amount == refund_lock2.amount assert lock2.secrethash assert lock2.expiration # channels have the amount locked because of the refund message assert_synched_channel_state( token_network_identifier, app0, deposit - amount_path, [lockstate_from_lock(lock1)], app1, deposit + amount_path, [lockstate_from_lock(refund_lock1)], ) assert_synched_channel_state( token_network_identifier, app1, deposit - amount_path, [lockstate_from_lock(lock2)], app2, deposit + amount_path, [lockstate_from_lock(refund_lock2)], ) assert_synched_channel_state( token_network_identifier, app2, deposit - amount_path - amount_drain, [], app3, deposit + amount_path + amount_drain, [], )
def test_secret_revealed(raiden_chain, deposit, settle_timeout, token_addresses): app0, app1, app2 = raiden_chain registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) amount = 10 identifier = 1 secret = pending_mediated_transfer( raiden_chain, token_network_identifier, amount, identifier, ) secrethash = sha3(secret) gevent.sleep(.1) # wait for the messages # The secret hasn't been revealed yet channel_state2_1 = get_channelstate(app2, app1, token_network_identifier) assert len(channel_state2_1.our_state.secrethashes_to_lockedlocks) == 1 channel.register_secret(channel_state2_1, secret, secrethash) # Close the channel # This needs to register the secrets on chain netting_channel_proxy = app2.raiden.chain.payment_channel( token_network_identifier, channel_state2_1.identifier, ) netting_channel_proxy.channel_close( registry_address, channel_state2_1.partner_state.balance_proof, ) settle_expiration = app0.raiden.chain.block_number() + settle_timeout wait_until_block(app0.raiden.chain, settle_expiration) assert_synched_channel_state( token_address, app1, deposit - amount, [], app2, deposit + amount, [], ) assert_synched_channel_state( token_address, app0, deposit - amount, [], app1, deposit + amount, [], )
def test_channel_deposit(raiden_chain, deposit, retry_timeout, token_addresses): app0, app1 = raiden_chain token_address = token_addresses[0] registry_address = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) channel0 = get_channelstate(app0, app1, token_network_identifier) channel1 = get_channelstate(app1, app0, token_network_identifier) assert channel0 is None assert channel1 is None RaidenAPI(app0.raiden).channel_open(registry_address, token_address, app1.raiden.address) gevent.sleep(retry_timeout) assert_synched_channel_state( token_network_identifier, app0, 0, [], app1, 0, [], ) RaidenAPI(app0.raiden).set_total_channel_deposit( registry_address, token_address, app1.raiden.address, deposit, ) gevent.sleep(retry_timeout) assert_synched_channel_state( token_network_identifier, app0, deposit, [], app1, 0, [], ) RaidenAPI(app1.raiden).set_total_channel_deposit( registry_address, token_address, app0.raiden.address, deposit, ) gevent.sleep(retry_timeout) assert_synched_channel_state( token_network_identifier, app0, deposit, [], app1, deposit, [], )
def test_batch_unlock(raiden_network, token_addresses, secret_registry_address, deposit): """Batch unlock can be called after the channel is settled.""" alice_app, bob_app = raiden_network registry_address = alice_app.raiden.default_registry.address token_address = token_addresses[0] token_proxy = alice_app.raiden.chain.token(token_address) token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(alice_app), alice_app.raiden.default_registry.address, token_address, ) alice_initial_balance = token_proxy.balance_of(alice_app.raiden.address) bob_initial_balance = token_proxy.balance_of(bob_app.raiden.address) alice_to_bob_amount = 10 identifier = 1 secret = pending_mediated_transfer( raiden_network, token_network_identifier, alice_to_bob_amount, identifier, ) secrethash = sha3(secret) secret_registry_proxy = alice_app.raiden.chain.secret_registry( secret_registry_address, ) secret_registry_proxy.register_secret(secret) alice_bob_channel_state = get_channelstate(alice_app, bob_app, token_network_identifier) lock = channel.get_lock(alice_bob_channel_state.our_state, secrethash) assert lock assert lock.expiration > alice_app.raiden.get_block_number() assert lock.secrethash == sha3(secret) # This is the current state of the protocol: # # A -> B LockedTransfer # B -> A SecretRequest # - protocol didn't continue assert_synched_channel_state( token_network_identifier, alice_app, deposit, [lock], bob_app, deposit, [], ) # A ChannelClose event will be generated, this will be polled by both apps # and each must start a task for calling settle RaidenAPI(bob_app.raiden).channel_close( registry_address, token_address, alice_app.raiden.address, ) waiting.wait_for_settle( alice_app.raiden, registry_address, token_address, [alice_bob_channel_state.identifier], alice_app.raiden.alarm.sleep_time, ) # wait for the node to call batch unlock with gevent.Timeout(10): wait_for_batch_unlock( alice_app, token_network_identifier, alice_bob_channel_state.partner_state.address, alice_bob_channel_state.our_state.address, ) alice_new_balance = alice_initial_balance + deposit - alice_to_bob_amount bob_new_balance = bob_initial_balance + deposit + alice_to_bob_amount assert token_proxy.balance_of(alice_app.raiden.address) == alice_new_balance assert token_proxy.balance_of(bob_app.raiden.address) == bob_new_balance
def test_query_events(raiden_chain, token_addresses, deposit, settle_timeout, retry_timeout): app0, app1 = raiden_chain # pylint: disable=unbalanced-tuple-unpacking registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), registry_address, token_address, ) manager0 = app0.raiden.default_registry.token_network_by_token( token_address) channelcount0 = views.total_token_network_channels( views.state_from_app(app0), registry_address, token_address, ) events = get_token_network_registry_events( app0.raiden.chain, registry_address, events=ALL_EVENTS, ) assert must_have_event( events, { 'event': EVENT_TOKEN_NETWORK_CREATED, 'args': { 'token_network_address': to_checksum_address(manager0.address), 'token_address': to_checksum_address(token_address), }, }, ) events = get_token_network_registry_events( app0.raiden.chain, app0.raiden.default_registry.address, events=ALL_EVENTS, from_block=999999998, to_block=999999999, ) assert not events RaidenAPI(app0.raiden).channel_open( registry_address, token_address, app1.raiden.address, ) events = get_token_network_events( app0.raiden.chain, manager0.address, events=ALL_EVENTS, ) channel_id = channel_identifier(app0.raiden.address, app1.raiden.address) assert must_have_event( events, { 'event': EVENT_CHANNEL_OPENED, 'args': { 'participant1': to_checksum_address(app0.raiden.address), 'participant2': to_checksum_address(app1.raiden.address), 'settle_timeout': settle_timeout, 'channel_identifier': channel_id, }, }, ) events = get_token_network_events( app0.raiden.chain, manager0.address, events=ALL_EVENTS, from_block=999999998, to_block=999999999, ) assert not events # channel is created but not opened and without funds channelcount1 = views.total_token_network_channels( views.state_from_app(app0), registry_address, token_address, ) assert channelcount0 + 1 == channelcount1 assert_synched_channel_state( token_network_identifier, app0, 0, [], app1, 0, [], ) RaidenAPI(app0.raiden).set_total_channel_deposit( registry_address, token_address, app1.raiden.address, deposit, ) all_netting_channel_events = get_all_netting_channel_events( app0.raiden.chain, token_network_identifier, channel_id, ) deposit_events = get_netting_channel_deposit_events( app0.raiden.chain, token_network_identifier, channel_id, ) total_deposit_event = { 'event': EVENT_CHANNEL_DEPOSIT, 'args': { 'participant': to_checksum_address(app0.raiden.address), 'total_deposit': deposit, 'channel_identifier': channel_id, }, } assert must_have_event(deposit_events, total_deposit_event) assert must_have_event(all_netting_channel_events, total_deposit_event) RaidenAPI(app0.raiden).channel_close( registry_address, token_address, app1.raiden.address, ) all_netting_channel_events = get_all_netting_channel_events( app0.raiden.chain, token_network_identifier, channel_id, ) closed_events = get_netting_channel_closed_events( app0.raiden.chain, token_network_identifier, channel_id, ) closed_event = { 'event': EVENT_CHANNEL_CLOSED, 'args': { 'channel_identifier': channel_id, 'closing_participant': to_checksum_address(app0.raiden.address), }, } assert must_have_event(closed_events, closed_event) assert must_have_event(all_netting_channel_events, closed_event) settle_expiration = app0.raiden.chain.block_number() + settle_timeout + 5 wait_until_block(app0.raiden.chain, settle_expiration) all_netting_channel_events = get_all_netting_channel_events( app0.raiden.chain, token_network_identifier, channel_id, ) settled_events = get_netting_channel_settled_events( app0.raiden.chain, token_network_identifier, channel_id, ) settled_event = { 'event': EVENT_CHANNEL_SETTLED, 'args': { 'channel_identifier': channel_id, }, } assert must_have_event(settled_events, settled_event) assert must_have_event(all_netting_channel_events, settled_event)
def test_received_lockedtransfer_closedchannel( raiden_network, reveal_timeout, token_addresses, deposit, ): app0, app1 = raiden_network registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) channel0 = get_channelstate(app0, app1, token_network_identifier) RaidenAPI(app1.raiden).channel_close( registry_address, token_address, app0.raiden.address, ) wait_until_block( app0.raiden.chain, app0.raiden.chain.block_number() + 1, ) # Now receive one mediated transfer for the closed channel lock_amount = 10 payment_identifier = 1 expiration = reveal_timeout * 2 mediated_transfer_message = LockedTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=random.randint(0, UINT64_MAX), payment_identifier=payment_identifier, nonce=1, token_network_address=token_network_identifier, token=token_address, channel_identifier=channel0.identifier, transferred_amount=0, locked_amount=lock_amount, recipient=app1.raiden.address, locksroot=UNIT_SECRETHASH, lock=Lock(lock_amount, expiration, UNIT_SECRETHASH), target=app1.raiden.address, initiator=app0.raiden.address, fee=0, ) sign_and_inject( mediated_transfer_message, app0.raiden.private_key, app0.raiden.address, app1, ) # The local state must not change since the channel is already closed assert_synched_channel_state( token_network_identifier, app0, deposit, [], app1, deposit, [], )
def test_secret_revealed(raiden_chain, deposit, settle_timeout, token_addresses): app0, app1, app2 = raiden_chain registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) amount = 10 identifier = 1 secret = pending_mediated_transfer( raiden_chain, token_network_identifier, amount, identifier, ) secrethash = sha3(secret) gevent.sleep(.1) # wait for the messages channel_state2_1 = get_channelstate(app2, app1, token_network_identifier) # the secret hasn't been revealed yet (through messages) assert len(channel_state2_1.our_state.secrethashes_to_lockedlocks) == 1 proofs = list(channel.get_known_unlocks(channel_state2_1.our_state)) assert not proofs channel.register_secret(channel_state2_1, secret, secrethash) # Close the channel netting_channel_proxy = app2.raiden.chain.netting_channel( channel_state2_1.identifier) netting_channel_proxy.channel_close( registry_address, channel_state2_1.partner_state.balance_proof, ) # Reveal the secret through the blockchain (this needs to emit the # SecretRevealed event) for unlock_proof in channel.get_known_unlocks( channel_state2_1.partner_state): netting_channel_proxy.withdraw(unlock_proof) settle_expiration = app0.raiden.chain.block_number() + settle_timeout wait_until_block(app0.raiden.chain, settle_expiration) assert_synched_channel_state( token_address, app1, deposit - amount, [], app2, deposit + amount, [], ) assert_synched_channel_state( token_address, app0, deposit - amount, [], app1, deposit + amount, [], )
def test_received_lockedtransfer_closedchannel( raiden_network, reveal_timeout, token_addresses, deposit ): app0, app1 = raiden_network registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) channel0 = get_channelstate(app0, app1, token_network_identifier) RaidenAPI(app1.raiden).channel_close( registry_address, token_address, app0.raiden.address, ) wait_until_block( app0.raiden.chain, app0.raiden.chain.block_number() + 1, ) # Now receive one mediated transfer for the closed channel lock_amount = 10 payment_identifier = 1 expiration = reveal_timeout * 2 mediated_transfer_message = LockedTransfer( message_identifier=random.randint(0, UINT64_MAX), payment_identifier=payment_identifier, nonce=1, token_network_address=token_network_identifier, token=token_address, channel=channel0.identifier, transferred_amount=0, locked_amount=lock_amount, recipient=app1.raiden.address, locksroot=UNIT_SECRETHASH, lock=Lock(lock_amount, expiration, UNIT_SECRETHASH), target=app1.raiden.address, initiator=app0.raiden.address, fee=0 ) sign_and_inject( mediated_transfer_message, app0.raiden.private_key, app0.raiden.address, app1, ) # The local state must not change since the channel is already closed assert_synched_channel_state( token_network_identifier, app0, deposit, [], app1, deposit, [], )
def test_unlock(raiden_network, token_addresses, deposit): """Unlock can be called on a closed channel.""" alice_app, bob_app = raiden_network registry_address = alice_app.raiden.default_registry.address token_address = token_addresses[0] token_proxy = alice_app.raiden.chain.token(token_address) token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(alice_app), alice_app.raiden.default_registry.address, token_address, ) alice_initial_balance = token_proxy.balance_of(alice_app.raiden.address) bob_initial_balance = token_proxy.balance_of(bob_app.raiden.address) alice_to_bob_amount = 10 identifier = 1 secret = pending_mediated_transfer( raiden_network, token_network_identifier, alice_to_bob_amount, identifier, ) secrethash = sha3(secret) # This is the current state of the protocol: # # A -> B LockedTransfer # B -> A SecretRequest # - protocol didn't continue alice_bob_channel = get_channelstate(alice_app, bob_app, token_network_identifier) bob_alice_channel = get_channelstate(bob_app, alice_app, token_network_identifier) lock = channel.get_lock(alice_bob_channel.our_state, secrethash) assert lock assert_synched_channel_state( token_network_identifier, alice_app, deposit, [lock], bob_app, deposit, [], ) # get proof, that locked transfermessage was in merkle tree, with locked.root unlock_proof = channel.compute_proof_for_lock( alice_bob_channel.our_state, secret, lock, ) assert validate_proof( unlock_proof.merkle_proof, merkleroot(bob_alice_channel.partner_state.merkletree), sha3(lock.encoded), ) assert unlock_proof.lock_encoded == lock.encoded assert unlock_proof.secret == secret # A ChannelClose event will be generated, this will be polled by both apps # and each must start a task for calling settle RaidenAPI(bob_app.raiden).channel_close( registry_address, token_address, alice_app.raiden.address, ) # Unlock will not be called because the secret was not revealed assert lock.expiration > alice_app.raiden.chain.block_number() assert lock.secrethash == sha3(secret) nettingchannel_proxy = bob_app.raiden.chain.netting_channel( bob_alice_channel.identifier, ) nettingchannel_proxy.unlock(unlock_proof) waiting.wait_for_settle( alice_app.raiden, registry_address, token_address, [alice_bob_channel.identifier], alice_app.raiden.alarm.wait_time, ) alice_bob_channel = get_channelstate(alice_app, bob_app, token_network_identifier) bob_alice_channel = get_channelstate(bob_app, alice_app, token_network_identifier) alice_netted_balance = alice_initial_balance + deposit - alice_to_bob_amount bob_netted_balance = bob_initial_balance + deposit + alice_to_bob_amount assert token_proxy.balance_of( alice_app.raiden.address) == alice_netted_balance assert token_proxy.balance_of(bob_app.raiden.address) == bob_netted_balance # Now let's query the WAL to see if the state changes were logged as expected state_changes = alice_app.raiden.wal.storage.get_statechanges_by_identifier( from_identifier=0, to_identifier='latest', ) alice_bob_channel = get_channelstate(alice_app, bob_app, token_network_identifier) bob_alice_channel = get_channelstate(bob_app, alice_app, token_network_identifier) assert must_contain_entry( state_changes, ContractReceiveChannelUnlock, { 'payment_network_identifier': registry_address, 'token_address': token_address, 'channel_identifier': alice_bob_channel.identifier, 'secrethash': secrethash, 'secret': secret, 'receiver': bob_app.raiden.address, })
def test_recovery_happy_case( raiden_network, number_of_nodes, deposit, token_addresses, network_wait, skip_if_not_udp, ): app0, app1, app2 = raiden_network token_address = token_addresses[0] chain_state = views.state_from_app(app0) payment_network_id = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( chain_state, payment_network_id, token_address, ) # make a few transfers from app0 to app2 amount = 1 spent_amount = deposit - 2 for _ in range(spent_amount): mediated_transfer( app0, app2, token_network_identifier, amount, timeout=network_wait * number_of_nodes, ) app0.raiden.stop() host_port = (app0.raiden.config['host'], app0.raiden.config['port']) socket = server._udp_socket(host_port) new_transport = UDPTransport( app0.discovery, socket, app0.raiden.transport.throttle_policy, app0.raiden.config['transport'], ) app0_restart = App( app0.config, app0.raiden.chain, app0.raiden.default_registry, app0.raiden.default_secret_registry, new_transport, app0.raiden.discovery, ) app0.stop() del app0 # from here on the app0_restart should be used assert_synched_channel_state( token_network_identifier, app0_restart, deposit - spent_amount, [], app1, deposit + spent_amount, [], ) assert_synched_channel_state( token_network_identifier, app1, deposit - spent_amount, [], app2, deposit + spent_amount, [], ) # wait for the nodes' healthcheck to update the network statuses waiting.wait_for_healthy( app0_restart.raiden, app1.raiden.address, network_wait, ) waiting.wait_for_healthy( app1.raiden, app0_restart.raiden.address, network_wait, ) mediated_transfer( app2, app0_restart, token_network_identifier, amount, timeout=network_wait * number_of_nodes * 2, ) mediated_transfer( app0_restart, app2, token_network_identifier, amount, timeout=network_wait * number_of_nodes * 2, ) assert_synched_channel_state( token_network_identifier, app0_restart, deposit - spent_amount, [], app1, deposit + spent_amount, [], ) assert_synched_channel_state( token_network_identifier, app1, deposit - spent_amount, [], app2, deposit + spent_amount, [], )
def test_settle_is_automatically_called(raiden_network, token_addresses, deposit): """Settle is automatically called by one of the nodes.""" app0, app1 = raiden_network registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) channel_identifier = get_channelstate(app0, app1, token_network_identifier).identifier # A ChannelClose event will be generated, this will be polled by both apps # and each must start a task for calling settle RaidenAPI(app1.raiden).channel_close( registry_address, token_address, app0.raiden.address, ) waiting.wait_for_settle( app0.raiden, registry_address, token_address, [channel_identifier], app0.raiden.alarm.wait_time, ) assert_synched_channel_state( token_network_identifier, app0, deposit, [], app1, deposit, [], ) state_changes = app0.raiden.wal.storage.get_statechanges_by_identifier( from_identifier=0, to_identifier='latest', ) channel_state = get_channelstate(app0, app1, token_network_identifier) assert channel_state.close_transaction.finished_block_number assert channel_state.settle_transaction.finished_block_number assert must_contain_entry( state_changes, ContractReceiveChannelClosed, { 'token_network_identifier': token_network_identifier, 'channel_identifier': channel_identifier, 'closing_address': app1.raiden.address, 'closed_block_number': channel_state.close_transaction.finished_block_number, }) assert must_contain_entry( state_changes, ContractReceiveChannelSettled, { 'token_network_identifier': token_network_identifier, 'channel_identifier': channel_identifier, 'settle_block_number': channel_state.settle_transaction.finished_block_number, })
def test_query_events(raiden_chain, token_addresses, deposit, settle_timeout, events_poll_timeout): app0, app1 = raiden_chain # pylint: disable=unbalanced-tuple-unpacking registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), registry_address, token_address, ) manager0 = app0.raiden.default_registry.manager_by_token(token_address) channelcount0 = views.total_token_network_channels( views.state_from_app(app0), registry_address, token_address, ) events = get_all_registry_events( app0.raiden.chain, registry_address, events=ALL_EVENTS, from_block=0, to_block='latest', ) assert len(events) == 1 assert events[0]['event'] == EVENT_TOKEN_ADDED assert event_dicts_are_equal(events[0]['args'], { 'registry_address': to_normalized_address(registry_address), 'channel_manager_address': to_normalized_address(manager0.address), 'token_address': to_normalized_address(token_address), 'block_number': 'ignore', }) events = get_all_registry_events( app0.raiden.chain, app0.raiden.default_registry.address, events=ALL_EVENTS, from_block=999999998, to_block=999999999, ) assert not events channel_address = RaidenAPI(app0.raiden).channel_open( registry_address, token_address, app1.raiden.address, ) gevent.sleep(events_poll_timeout * 2) events = get_all_channel_manager_events( app0.raiden.chain, manager0.address, events=ALL_EVENTS, from_block=0, to_block='latest', ) assert len(events) == 1 assert events[0]['event'] == EVENT_CHANNEL_NEW assert event_dicts_are_equal(events[0]['args'], { 'registry_address': to_normalized_address(registry_address), 'settle_timeout': settle_timeout, 'netting_channel': to_normalized_address(channel_address), 'participant1': to_normalized_address(app0.raiden.address), 'participant2': to_normalized_address(app1.raiden.address), 'block_number': 'ignore', }) events = get_all_channel_manager_events( app0.raiden.chain, manager0.address, events=ALL_EVENTS, from_block=999999998, to_block=999999999, ) assert not events # channel is created but not opened and without funds channelcount1 = views.total_token_network_channels( views.state_from_app(app0), registry_address, token_address, ) assert channelcount0 + 1 == channelcount1 assert_synched_channel_state( token_network_identifier, app0, 0, [], app1, 0, [], ) RaidenAPI(app0.raiden).channel_deposit( registry_address, token_address, app1.raiden.address, deposit, ) gevent.sleep(events_poll_timeout * 2) all_netting_channel_events = get_all_netting_channel_events( app0.raiden.chain, channel_address, from_block=0, to_block='latest', ) events = get_all_netting_channel_events( app0.raiden.chain, channel_address, events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_NEW_BALANCE)], ) assert len(all_netting_channel_events) == 1 assert len(events) == 1 assert events[0]['event'] == EVENT_CHANNEL_NEW_BALANCE new_balance_event = { 'registry_address': to_normalized_address(registry_address), 'token_address': to_normalized_address(token_address), 'participant': to_normalized_address(app0.raiden.address), 'balance': deposit, 'block_number': 'ignore', } assert event_dicts_are_equal(all_netting_channel_events[-1]['args'], new_balance_event) assert event_dicts_are_equal(events[0]['args'], new_balance_event) RaidenAPI(app0.raiden).channel_close( registry_address, token_address, app1.raiden.address, ) gevent.sleep(events_poll_timeout * 2) all_netting_channel_events = get_all_netting_channel_events( app0.raiden.chain, netting_channel_address=channel_address, from_block=0, to_block='latest', ) events = get_all_netting_channel_events( app0.raiden.chain, channel_address, events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_CLOSED)], ) assert len(all_netting_channel_events) == 2 assert len(events) == 1 assert events[0]['event'] == EVENT_CHANNEL_CLOSED closed_event = { 'registry_address': to_normalized_address(registry_address), 'closing_address': to_normalized_address(app0.raiden.address), 'block_number': 'ignore', } assert event_dicts_are_equal(all_netting_channel_events[-1]['args'], closed_event) assert event_dicts_are_equal(events[0]['args'], closed_event) settle_expiration = app0.raiden.chain.block_number() + settle_timeout + 5 wait_until_block(app0.raiden.chain, settle_expiration) all_netting_channel_events = get_all_netting_channel_events( app0.raiden.chain, netting_channel_address=channel_address, from_block=0, to_block='latest', ) events = get_all_netting_channel_events( app0.raiden.chain, channel_address, events=[CONTRACT_MANAGER.get_event_id(EVENT_CHANNEL_SETTLED)], ) assert len(all_netting_channel_events) == 3 assert len(events) == 1 assert events[0]['event'] == EVENT_CHANNEL_SETTLED settled_event = { 'registry_address': to_normalized_address(registry_address), 'block_number': 'ignore', } assert event_dicts_are_equal(all_netting_channel_events[-1]['args'], settled_event) assert event_dicts_are_equal(events[0]['args'], settled_event)
def test_refund_transfer_after_2nd_hop( raiden_chain, number_of_nodes, token_addresses, deposit, network_wait, ): """Test the refund transfer sent due to failure after 2nd hop""" # Topology: # # 0 -> 1 -> 2 -> 3 # app0, app1, app2, app3 = raiden_chain token_address = token_addresses[0] payment_network_identifier = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), payment_network_identifier, token_address, ) # make a transfer to test the path app0 -> app1 -> app2 -> app3 identifier_path = 1 amount_path = 1 mediated_transfer( app0, app3, token_network_identifier, amount_path, identifier_path, timeout=network_wait * number_of_nodes, ) # drain the channel app2 -> app3 identifier_drain = 2 amount_drain = deposit * 8 // 10 direct_transfer( app2, app3, token_network_identifier, amount_drain, identifier_drain, timeout=network_wait, ) # wait for the nodes to sync gevent.sleep(0.2) assert_synched_channel_state( token_network_identifier, app0, deposit - amount_path, [], app1, deposit + amount_path, [], ) assert_synched_channel_state( token_network_identifier, app1, deposit - amount_path, [], app2, deposit + amount_path, [], ) assert_synched_channel_state( token_network_identifier, app2, deposit - amount_path - amount_drain, [], app3, deposit + amount_path + amount_drain, [], ) # app0 -> app1 -> app2 > app3 is the only available path, but the channel # app2 -> app3 doesn't have capacity, so a refund will be sent on # app2 -> app1 -> app0 identifier_refund = 3 amount_refund = 50 async_result = app0.raiden.mediated_transfer_async( token_network_identifier, amount_refund, app3.raiden.address, identifier_refund, ) assert async_result.wait() is False, 'there is no path with capacity, the transfer must fail' gevent.sleep(0.2) # Lock structures with the correct amount send_locked1 = raiden_events_must_contain_entry( app0.raiden, SendLockedTransfer, {'transfer': {'lock': {'amount': amount_refund}}}, ) assert send_locked1 send_refund1 = raiden_events_must_contain_entry(app1.raiden, SendRefundTransfer, {}) assert send_refund1 lock1 = send_locked1.transfer.lock refund_lock1 = send_refund1.lock assert lock1.amount == refund_lock1.amount assert lock1.secrethash == refund_lock1.secrethash send_locked2 = raiden_events_must_contain_entry( app1.raiden, SendLockedTransfer, {'transfer': {'lock': {'amount': amount_refund}}}, ) assert send_locked2 send_refund2 = raiden_events_must_contain_entry(app2.raiden, SendRefundTransfer, {}) assert send_refund2 lock2 = send_locked2.transfer.lock refund_lock2 = send_refund2.lock assert lock2.amount == refund_lock2.amount assert lock2.secrethash assert lock2.expiration # channels have the amount locked because of the refund message assert_synched_channel_state( token_network_identifier, app0, deposit - amount_path, [lockstate_from_lock(lock1)], app1, deposit + amount_path, [lockstate_from_lock(refund_lock1)], ) assert_synched_channel_state( token_network_identifier, app1, deposit - amount_path, [lockstate_from_lock(lock2)], app2, deposit + amount_path, [lockstate_from_lock(refund_lock2)], ) assert_synched_channel_state( token_network_identifier, app2, deposit - amount_path - amount_drain, [], app3, deposit + amount_path + amount_drain, [], )
def test_batch_unlock(raiden_network, token_addresses, secret_registry_address, deposit): """Batch unlock can be called after the channel is settled.""" alice_app, bob_app = raiden_network registry_address = alice_app.raiden.default_registry.address token_address = token_addresses[0] token_proxy = alice_app.raiden.chain.token(token_address) token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(alice_app), alice_app.raiden.default_registry.address, token_address, ) alice_initial_balance = token_proxy.balance_of(alice_app.raiden.address) bob_initial_balance = token_proxy.balance_of(bob_app.raiden.address) alice_to_bob_amount = 10 identifier = 1 secret = pending_mediated_transfer( raiden_network, token_network_identifier, alice_to_bob_amount, identifier, ) secrethash = sha3(secret) secret_registry_proxy = alice_app.raiden.chain.secret_registry( secret_registry_address, ) secret_registry_proxy.register_secret(secret) alice_bob_channel_state = get_channelstate(alice_app, bob_app, token_network_identifier) lock = channel.get_lock(alice_bob_channel_state.our_state, secrethash) assert lock assert lock.expiration > alice_app.raiden.get_block_number() assert lock.secrethash == sha3(secret) # This is the current state of the protocol: # # A -> B LockedTransfer # B -> A SecretRequest # - protocol didn't continue assert_synched_channel_state( token_network_identifier, alice_app, deposit, [lock], bob_app, deposit, [], ) # A ChannelClose event will be generated, this will be polled by both apps # and each must start a task for calling settle RaidenAPI(bob_app.raiden).channel_close( registry_address, token_address, alice_app.raiden.address, ) waiting.wait_for_settle( alice_app.raiden, registry_address, token_address, [alice_bob_channel_state.identifier], alice_app.raiden.alarm.wait_time, ) # wait for the node to call batch unlock with gevent.Timeout(10): wait_for_batch_unlock( alice_app, alice_bob_channel_state.identifier, token_network_identifier, ) alice_new_balance = alice_initial_balance + deposit - alice_to_bob_amount bob_new_balance = bob_initial_balance + deposit + alice_to_bob_amount assert token_proxy.balance_of(alice_app.raiden.address) == alice_new_balance assert token_proxy.balance_of(bob_app.raiden.address) == bob_new_balance
def test_refund_transfer(raiden_chain, number_of_nodes, token_addresses, deposit, network_wait): """A failed transfer must send a refund back. TODO: - Unlock the token on refund #1091 - Clear the merkletree and update the locked amount #193 - Remove the refund message type #490""" # Topology: # # 0 -> 1 -> 2 # app0, app1, app2 = raiden_chain token_address = token_addresses[0] payment_network_identifier = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), payment_network_identifier, token_address, ) # make a transfer to test the path app0 -> app1 -> app2 identifier_path = 1 amount_path = 1 mediated_transfer( app0, app2, token_network_identifier, amount_path, identifier_path, timeout=network_wait * number_of_nodes, ) # drain the channel app1 -> app2 identifier_drain = 2 amount_drain = deposit * 8 // 10 direct_transfer( app1, app2, token_network_identifier, amount_drain, identifier_drain, timeout=network_wait, ) # wait for the nodes to sync gevent.sleep(0.2) assert_synched_channel_state( token_network_identifier, app0, deposit - amount_path, [], app1, deposit + amount_path, [], ) assert_synched_channel_state( token_network_identifier, app1, deposit - amount_path - amount_drain, [], app2, deposit + amount_path + amount_drain, [], ) # app0 -> app1 -> app2 is the only available path, but the channel app1 -> # app2 doesn't have capacity, so a refund will be sent on app1 -> app0 identifier_refund = 3 amount_refund = 50 async_result = app0.raiden.mediated_transfer_async( token_network_identifier, amount_refund, app2.raiden.address, identifier_refund, ) assert async_result.wait() is False, 'there is no path with capacity, the transfer must fail' gevent.sleep(0.2) # A lock structure with the correct amount send_locked = raiden_events_must_contain_entry( app0.raiden, SendLockedTransfer, {'transfer': {'lock': {'amount': amount_refund}}}, ) assert send_locked send_refund = raiden_events_must_contain_entry(app1.raiden, SendRefundTransfer, {}) assert send_refund lock = send_locked.transfer.lock refund_lock = send_refund.lock assert lock.amount == refund_lock.amount assert lock.secrethash assert lock.expiration # Both channels have the amount locked because of the refund message assert_synched_channel_state( token_network_identifier, app0, deposit - amount_path, [lockstate_from_lock(lock)], app1, deposit + amount_path, [lockstate_from_lock(refund_lock)], ) assert_synched_channel_state( token_network_identifier, app1, deposit - amount_path - amount_drain, [], app2, deposit + amount_path + amount_drain, [], )
def test_refund_transfer(raiden_chain, token_addresses, deposit, network_wait): """A failed transfer must send a refund back. TODO: - Unlock the token on refund #1091 - Clear the merkletree and update the locked amount #193 - Remove the refund message type #490""" # Topology: # # 0 -> 1 -> 2 # app0, app1, app2 = raiden_chain token_address = token_addresses[0] # make a transfer to test the path app0 -> app1 -> app2 identifier_path = 1 amount_path = 1 mediated_transfer( app0, app2, token_address, amount_path, identifier_path, timeout=network_wait, ) # drain the channel app1 -> app2 identifier_drain = 2 amount_drain = deposit * 8 // 10 direct_transfer( app1, app2, token_address, amount_drain, identifier_drain, timeout=network_wait, ) # wait for the nodes to sync gevent.sleep(0.2) assert_synched_channel_state( token_address, app0, deposit - amount_path, [], app1, deposit + amount_path, [], ) assert_synched_channel_state( token_address, app1, deposit - amount_path - amount_drain, [], app2, deposit + amount_path + amount_drain, [], ) # app0 -> app1 -> app2 is the only available path, but the channel app1 -> # app2 doesn't have capacity, so a refund will be sent on app1 -> app0 identifier_refund = 3 amount_refund = 50 async_result = app0.raiden.mediated_transfer_async( token_address, amount_refund, app2.raiden.address, identifier_refund, ) assert async_result.wait( ) is False, 'there is no path with capacity, the transfer must fail' gevent.sleep(0.2) # A lock structure with the correct amount app0_messages = app0.raiden.protocol.transport.get_sent_messages( app0.raiden.address) mediated_message = list(message for message in app0_messages if isinstance(message, LockedTransfer) and message.target == app2.raiden.address)[-1] assert mediated_message app1_messages = app1.raiden.protocol.transport.get_sent_messages( app1.raiden.address) refund_message = next(message for message in app1_messages if isinstance(message, RefundTransfer) and message.recipient == app0.raiden.address) assert refund_message assert mediated_message.lock.amount == refund_message.lock.amount assert mediated_message.lock.secrethash == refund_message.lock.secrethash assert mediated_message.lock.expiration > refund_message.lock.expiration # Both channels have the amount locked because of the refund message assert_synched_channel_state( token_address, app0, deposit - amount_path, [lockstate_from_lock(mediated_message.lock)], app1, deposit + amount_path, [lockstate_from_lock(refund_message.lock)], ) assert_synched_channel_state( token_address, app1, deposit - amount_path - amount_drain, [], app2, deposit + amount_path + amount_drain, [], )
def test_receive_lockedtransfer_invalidnonce( raiden_network, deposit, token_addresses, reveal_timeout, network_wait, ): app0, app1, app2 = raiden_network token_address = token_addresses[0] token_network_identifier = views.get_token_network_identifier_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address, ) channel0 = get_channelstate(app0, app1, token_network_identifier) amount = 10 mediated_transfer( app0, app2, token_network_identifier, amount, timeout=network_wait, ) amount = 10 payment_identifier = 1 repeated_nonce = 1 expiration = reveal_timeout * 2 mediated_transfer_message = LockedTransfer( message_identifier=random.randint(0, UINT64_MAX), payment_identifier=payment_identifier, nonce=repeated_nonce, token_network_address=token_network_identifier, token=token_address, channel=channel0.identifier, transferred_amount=amount, locked_amount=amount, recipient=app1.raiden.address, locksroot=UNIT_SECRETHASH, lock=Lock(amount, expiration, UNIT_SECRETHASH), target=app2.raiden.address, initiator=app0.raiden.address, fee=0, ) sign_and_inject( mediated_transfer_message, app0.raiden.private_key, app0.raiden.address, app1, ) assert_synched_channel_state( token_network_identifier, app0, deposit - amount, [], app1, deposit + amount, [], )
def test_recovery_unhappy_case( raiden_network, number_of_nodes, deposit, token_addresses, network_wait, skip_if_not_udp, retry_timeout, ): app0, app1, app2 = raiden_network token_address = token_addresses[0] chain_state = views.state_from_app(app0) payment_network_id = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( chain_state, payment_network_id, token_address, ) # make a few transfers from app0 to app2 amount = 1 spent_amount = deposit - 2 for _ in range(spent_amount): mediated_transfer( app0, app2, token_network_identifier, amount, timeout=network_wait * number_of_nodes, ) app0.raiden.stop() host_port = (app0.raiden.config['host'], app0.raiden.config['port']) socket = server._udp_socket(host_port) new_transport = UDPTransport( app0.discovery, socket, app0.raiden.transport.throttle_policy, app0.raiden.config['transport'], ) app0.stop() RaidenAPI(app1.raiden).channel_close( app1.raiden.default_registry.address, token_address, app0.raiden.address, ) channel01 = views.get_channelstate_for( views.state_from_app(app1), app1.raiden.default_registry.address, token_address, app0.raiden.address, ) waiting.wait_for_settle( app1.raiden, app1.raiden.default_registry.address, token_address, [channel01.identifier], retry_timeout, ) app0_restart = App( config=app0.config, chain=app0.raiden.chain, query_start_block=0, default_registry=app0.raiden.default_registry, default_secret_registry=app0.raiden.default_secret_registry, transport=new_transport, discovery=app0.raiden.discovery, ) del app0 # from here on the app0_restart should be used assert_synched_channel_state( token_network_identifier, app0_restart, deposit - spent_amount, [], app1, deposit + spent_amount, [], ) assert_synched_channel_state( token_network_identifier, app1, deposit - spent_amount, [], app2, deposit + spent_amount, [], )