def test_stress( raiden_network: List[App], restart_node: RestartNode, deposit: TokenAmount, retry_timeout: float, token_addresses: List[TokenAddress], port_generator: Iterator[Port], ) -> None: token_address = token_addresses[0] rest_apis = start_apiserver_for_network(raiden_network, port_generator) identifier_generator = count(start=1) token_network_address = views.get_token_network_address_by_token_address( views.state_from_app(raiden_network[0]), raiden_network[0].raiden.default_registry.address, token_address, ) assert token_network_address for _ in range(2): assert_channels(raiden_network, token_network_address, deposit) with watch_for_unlock_failures(*raiden_network): stress_send_serial_transfers(rest_apis, token_address, identifier_generator, deposit) raiden_network, rest_apis = restart_network_and_apiservers( raiden_network, restart_node, rest_apis, port_generator, retry_timeout) assert_channels(raiden_network, token_network_address, deposit) with watch_for_unlock_failures(*raiden_network): stress_send_parallel_transfers(rest_apis, token_address, identifier_generator, deposit) raiden_network, rest_apis = restart_network_and_apiservers( raiden_network, restart_node, rest_apis, port_generator, retry_timeout) assert_channels(raiden_network, token_network_address, deposit) with watch_for_unlock_failures(*raiden_network): stress_send_and_receive_parallel_transfers(rest_apis, token_address, identifier_generator, deposit) raiden_network, rest_apis = restart_network_and_apiservers( raiden_network, restart_node, rest_apis, port_generator, retry_timeout) restart_network(raiden_network, restart_node, retry_timeout)
def test_regression_revealsecret_after_secret( raiden_network: List[App], token_addresses: List[TokenAddress]) -> None: """ A RevealSecret message received after a Unlock message must be cleanly handled. """ app0, app1, app2 = raiden_network token = token_addresses[0] identifier = PaymentID(1) token_network_registry_address = app0.raiden.default_registry.address token_network_address = views.get_token_network_address_by_token_address( views.state_from_app(app0), token_network_registry_address, token) assert token_network_address, "The fixtures must register the token" payment_status = app0.raiden.mediated_transfer_async( token_network_address, amount=PaymentAmount(1), target=TargetAddress(app2.raiden.address), identifier=identifier, ) with watch_for_unlock_failures(*raiden_network): assert payment_status.payment_done.wait() assert app1.raiden.wal, "The fixtures must start the app." event = raiden_events_search_for_item(app1.raiden, SendSecretReveal, {}) assert event reveal_secret = RevealSecret( message_identifier=make_message_identifier(), secret=event.secret, signature=EMPTY_SIGNATURE, ) app2.raiden.sign(reveal_secret) app1.raiden.on_messages([reveal_secret])
def test_regression_revealsecret_after_secret(raiden_network, token_addresses, transport_protocol): """ A RevealSecret message received after a Unlock message must be cleanly handled. """ app0, app1, app2 = raiden_network token = token_addresses[0] identifier = 1 token_network_registry_address = app0.raiden.default_registry.address token_network_address = views.get_token_network_address_by_token_address( views.state_from_app(app0), token_network_registry_address, token) payment_status = app0.raiden.mediated_transfer_async( token_network_address, amount=1, target=app2.raiden.address, identifier=identifier) with watch_for_unlock_failures(*raiden_network): assert payment_status.payment_done.wait() event = search_for_item(app1.raiden.wal.storage.get_events(), SendSecretReveal, {}) assert event reveal_secret = RevealSecret( message_identifier=make_message_identifier(), secret=event.secret, signature=EMPTY_SIGNATURE, ) app2.raiden.sign(reveal_secret) if transport_protocol is TransportProtocol.MATRIX: app1.raiden.transport._receive_message(reveal_secret) # pylint: disable=protected-access else: raise TypeError("Unknown TransportProtocol")
def test_close_regression(raiden_network, deposit, token_addresses): """ The python api was using the wrong balance proof to close the channel, thus the close was failing if a transfer was made. """ app0, app1 = raiden_network token_address = token_addresses[0] api1 = RaidenAPI(app0.raiden) api2 = RaidenAPI(app1.raiden) registry_address = app0.raiden.default_registry.address channel_list = api1.get_channel_list(registry_address, token_address, app1.raiden.address) channel12 = channel_list[0] token_proxy = app0.raiden.proxy_manager.token(token_address, BLOCK_ID_LATEST) node1_balance_before = token_proxy.balance_of(api1.address) node2_balance_before = token_proxy.balance_of(api2.address) # Initialize app2 balance proof and close the channel amount = PaymentAmount(10) identifier = PaymentID(42) secret, secrethash = factories.make_secret_with_hash() timeout = block_offset_timeout(app1.raiden, "Transfer timed out.") with watch_for_unlock_failures(*raiden_network), timeout: assert api1.transfer_and_wait( registry_address=registry_address, token_address=token_address, amount=amount, target=TargetAddress(api2.address), identifier=identifier, secret=secret, ) timeout.exception_to_throw = ValueError( "Waiting for transfer received success in the WAL timed out.") result = waiting.wait_for_received_transfer_result( raiden=app1.raiden, payment_identifier=identifier, amount=amount, retry_timeout=app1.raiden.alarm.sleep_time, secrethash=secrethash, ) msg = f"Unexpected transfer result: {str(result)}" assert result == waiting.TransferWaitResult.UNLOCKED, msg api2.channel_close(registry_address, token_address, api1.address) waiting.wait_for_settle( app0.raiden, app0.raiden.default_registry.address, token_address, [channel12.identifier], app0.raiden.alarm.sleep_time, ) node1_expected_balance = node1_balance_before + deposit - amount node2_expected_balance = node2_balance_before + deposit + amount assert token_proxy.balance_of(api1.address) == node1_expected_balance assert token_proxy.balance_of(api2.address) == node2_expected_balance
def test_api_payments_with_secret_and_hash(api_server_test_instance: APIServer, raiden_network, token_addresses): _, app1 = raiden_network amount = 100 identifier = 42 token_address = token_addresses[0] target_address = app1.raiden.address secret = to_hex(factories.make_secret()) secret_hash = to_hex(sha256(to_bytes(hexstr=secret)).digest()) our_address = api_server_test_instance.rest_api.raiden_api.address payment = { "initiator_address": to_checksum_address(our_address), "target_address": to_checksum_address(target_address), "token_address": to_checksum_address(token_address), "amount": str(amount), "identifier": str(identifier), } request = grequests.post( api_url_for( api_server_test_instance, "token_target_paymentresource", token_address=to_checksum_address(token_address), target_address=to_checksum_address(target_address), ), json={ "amount": str(amount), "identifier": str(identifier), "secret": secret, "secret_hash": secret_hash, }, ) with watch_for_unlock_failures(*raiden_network): response = request.send().response assert_proper_response(response) json_response = get_json_response(response) assert_payment_secret_and_hash(json_response, payment) assert secret == json_response["secret"] assert secret_hash == json_response["secret_hash"]
def test_api_payments_with_secret_and_hash(api_server_test_instance: APIServer, raiden_network: List[RaidenService], token_addresses): _, app1 = raiden_network token_address = token_addresses[0] target_address = app1.address secret, secret_hash = factories.make_secret_with_hash() our_address = api_server_test_instance.rest_api.raiden_api.address payment = { "initiator_address": to_checksum_address(our_address), "target_address": to_checksum_address(target_address), "token_address": to_checksum_address(token_address), "amount": DEFAULT_AMOUNT, "identifier": DEFAULT_ID, } request = grequests.post( api_url_for( api_server_test_instance, "token_target_paymentresource", token_address=to_checksum_address(token_address), target_address=to_checksum_address(target_address), ), json={ "amount": DEFAULT_AMOUNT, "identifier": DEFAULT_ID, "secret": to_hex(secret), "secret_hash": to_hex(secret_hash), }, ) with watch_for_unlock_failures(*raiden_network): response = request.send().response assert_proper_response(response) json_response = get_json_response(response) assert_payment_secret_and_hash(json_response, payment) assert to_hex(secret) == json_response["secret"] assert to_hex(secret_hash) == json_response["secret_hash"]
def test_payment_events_endpoints(api_server_test_instance: APIServer, raiden_network: List[RaidenService], token_addresses): app0, app1, app2 = raiden_network token_address0 = token_addresses[0] token_address1 = token_addresses[1] app0_server = api_server_test_instance app1_server = prepare_api_server(app1) app2_server = prepare_api_server(app2) # Payment 1: app0 is sending tokens of token0 to app1 identifier1 = PaymentID(10) amount1 = PaymentAmount(10) secret1, secrethash1 = factories.make_secret_with_hash() request = grequests.post( api_url_for( app0_server, "token_target_paymentresource", token_address=to_checksum_address(token_address0), target_address=to_checksum_address(app1.address), ), json={ "amount": str(amount1), "identifier": str(identifier1), "secret": to_hex(secret1) }, ) request.send() # Payment 2: app0 is sending some tokens of token1 to app2 identifier2 = PaymentID(20) amount2 = PaymentAmount(10) secret2, secrethash2 = factories.make_secret_with_hash() request = grequests.post( api_url_for( app0_server, "token_target_paymentresource", token_address=to_checksum_address(token_address1), target_address=to_checksum_address(app2.address), ), json={ "amount": str(amount2), "identifier": str(identifier2), "secret": to_hex(secret2) }, ) request.send() # Payment 3: app0 is sending some tokens of token0 to app2 identifier3 = PaymentID(30) amount3 = PaymentAmount(17) secret3, secrethash3 = factories.make_secret_with_hash() request = grequests.post( api_url_for( app0_server, "token_target_paymentresource", token_address=to_checksum_address(token_address0), target_address=to_checksum_address(app1.address), ), json={ "amount": str(amount3), "identifier": str(identifier3), "secret": to_hex(secret3) }, ) request.send() timeout = block_offset_timeout( app2, "Waiting for transfer received success in the WAL timed out") with watch_for_unlock_failures(*raiden_network), timeout: result = wait_for_received_transfer_result(app1, identifier1, amount1, app1.alarm.sleep_time, secrethash1) msg = f"Unexpected transfer result: {str(result)}" assert result == TransferWaitResult.UNLOCKED, msg result = wait_for_received_transfer_result(app2, identifier2, amount2, app2.alarm.sleep_time, secrethash2) msg = f"Unexpected transfer result: {str(result)}" assert result == TransferWaitResult.UNLOCKED, msg result = wait_for_received_transfer_result(app1, identifier3, amount3, app1.alarm.sleep_time, secrethash3) msg = f"Unexpected transfer result: {str(result)}" assert result == TransferWaitResult.UNLOCKED, msg # predefine events for later use in assertions event_sent_1 = { "event": "EventPaymentSentSuccess", "identifier": str(identifier1), "target": to_checksum_address(app1.address), "token_address": to_checksum_address(token_address0), } event_sent_2 = { "event": "EventPaymentSentSuccess", "identifier": str(identifier2), "target": to_checksum_address(app2.address), "token_address": to_checksum_address(token_address1), } event_sent_3 = { "event": "EventPaymentSentSuccess", "identifier": str(identifier3), "target": to_checksum_address(app1.address), "token_address": to_checksum_address(token_address0), } event_received_1 = { "event": "EventPaymentReceivedSuccess", "identifier": str(identifier1), "initiator": to_checksum_address(app0.address), "token_address": to_checksum_address(token_address0), } event_received_2 = { "event": "EventPaymentReceivedSuccess", "identifier": str(identifier2), "initiator": to_checksum_address(app0.address), "token_address": to_checksum_address(token_address1), } event_received_3 = { "event": "EventPaymentReceivedSuccess", "identifier": str(identifier3), "initiator": to_checksum_address(app0.address), "token_address": to_checksum_address(token_address0), } # test app0 endpoint without (partner and token) for sender request = grequests.get(api_url_for(app0_server, "paymentresource")) with watch_for_unlock_failures(*raiden_network): response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert must_have_event(json_response, event_sent_1) assert must_have_event(json_response, event_sent_2) assert must_have_event(json_response, event_sent_3) # test endpoint without (partner and token) for target1 request = grequests.get(api_url_for(app1_server, "paymentresource")) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert must_have_event(json_response, event_received_1) assert must_have_event(json_response, event_received_3) # test endpoint without (partner and token) for target2 request = grequests.get(api_url_for(app2_server, "paymentresource")) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert must_have_event(json_response, event_received_2) # test endpoint without partner for app0 request = grequests.get( api_url_for(app0_server, "token_paymentresource", token_address=token_address0)) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert must_have_event(json_response, event_sent_1) assert must_have_event(json_response, event_sent_3) # test endpoint without partner for app0 but with limit/offset to get only first request = grequests.get( api_url_for( app0_server, "token_paymentresource", token_address=token_address0, limit=1, offset=0, )) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert must_have_event(json_response, event_sent_1) assert len(json_response) == 1 # test endpoint without partner for app0 but with limit/offset # to get only second transfer of token_address request = grequests.get( api_url_for( app0_server, "token_paymentresource", token_address=token_address0, limit=1, offset=1, )) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) # this should return only payment 3, since payment 1 is offset # and payment 2 is of another token address assert len(json_response) == 1 assert must_have_event(json_response, event_sent_3) # test endpoint of app1 without partner for token_address request = grequests.get( api_url_for(app1_server, "token_paymentresource", token_address=token_address0)) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert must_have_events(json_response, event_received_1) assert must_have_events(json_response, event_received_3) # test endpoint of app2 without partner for token_address request = grequests.get( api_url_for(app2_server, "token_paymentresource", token_address=token_address0)) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert len(json_response) == 0 # test endpoint of app2 without partner for token_address2 request = grequests.get( api_url_for(app2_server, "token_paymentresource", token_address=token_address1)) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert must_have_events(json_response, event_received_2) # test endpoint for token_address0 and partner for app0 request = grequests.get( api_url_for( app0_server, "token_target_paymentresource", token_address=token_address0, target_address=app1.address, )) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert len(json_response) == 2 assert must_have_event(json_response, event_sent_1) assert must_have_event(json_response, event_sent_3) request = grequests.get( api_url_for( app0_server, "token_target_paymentresource", token_address=token_address1, target_address=app2.address, )) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert len(json_response) == 1 assert must_have_event(json_response, event_sent_2) # test endpoint for token_address0 and partner for app1. Check both partners # to see that filtering works correctly request = grequests.get( api_url_for( app1_server, "token_target_paymentresource", token_address=token_address0, target_address=app2.address, )) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert len(json_response) == 0 request = grequests.get( api_url_for( app1_server, "token_target_paymentresource", token_address=token_address0, target_address=app0.address, )) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert len(json_response) == 2 assert must_have_event(json_response, event_received_1) assert must_have_event(json_response, event_received_3) # test app1 checking payments to himself request = grequests.get( api_url_for( app1_server, "token_target_paymentresource", token_address=token_address0, target_address=app1.address, )) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert len(json_response) == 0 # test endpoint for token and partner for app2 request = grequests.get( api_url_for( app2_server, "token_target_paymentresource", token_address=token_address0, target_address=app0.address, )) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) # Since app2 has no payment with app0 in token_address assert len(json_response) == 0 # test endpoint for token2 and partner for app2 request = grequests.get( api_url_for( app2_server, "token_target_paymentresource", token_address=token_address1, target_address=app0.address, )) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) # app2 has one payment with app0 in token_address2 assert len(json_response) == 1 assert must_have_events(json_response, event_received_2) request = grequests.get( api_url_for( app2_server, "token_target_paymentresource", token_address=token_address0, target_address=app1.address, )) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert not must_have_event(json_response, event_received_2) # also add a test for filtering by wrong token address request = grequests.get( api_url_for( app2_server, "token_target_paymentresource", token_address=app1.address, target_address=app1.address, )) response = request.send().response assert_proper_response(response, HTTPStatus.BAD_REQUEST) app1_server.stop() app2_server.stop()
def test_echo_node_response(token_addresses, raiden_chain, retry_timeout): app0, app1, echo_app = raiden_chain token_address = token_addresses[0] registry_address = echo_app.raiden.default_registry.address echo_api = RaidenAPI(echo_app.raiden) echo_node = EchoNode(echo_api, token_address) message_handler = WaitForMessage() echo_app.raiden.message_handler = message_handler echo_node.ready.wait(timeout=30) assert echo_node.ready.is_set() transfer_timeout = 10 wait_for = list() for num, app in enumerate([app0, app1]): amount = PaymentAmount(1 + num) identifier = PaymentID(10 ** (num + 1)) secret, secrethash = make_secret_with_hash() payment_status = RaidenAPI(app.raiden).transfer_async( registry_address=registry_address, token_address=token_address, amount=amount, target=echo_app.raiden.address, identifier=identifier, secret=secret, secrethash=secrethash, ) wait = message_handler.wait_for_message(Unlock, {"secret": secret}) wait_for.append((wait, app.raiden.address, amount, identifier)) msg = ( f"Transfer {identifier} from " f"{to_checksum_address(app.raiden.address)} to " f"{to_checksum_address(echo_app.raiden.address)} timed out after " f"{transfer_timeout}" ) timeout = gevent.Timeout(transfer_timeout, exception=RuntimeError(msg)) with watch_for_unlock_failures(*raiden_chain), timeout: payment_status.payment_done.wait() echo_identifier = PaymentID(identifier + amount) msg = ( f"Response transfer {echo_identifier} from echo node " f"{to_checksum_address(echo_app.raiden.address)} to " f"{to_checksum_address(app.raiden.address)} timed out after " f"{transfer_timeout}" ) with gevent.Timeout(transfer_timeout, exception=RuntimeError(msg)): result = wait_for_received_transfer_result( raiden=app.raiden, payment_identifier=echo_identifier, amount=amount, retry_timeout=retry_timeout, secrethash=secrethash, ) assert result == TransferWaitResult.UNLOCKED for wait, sender, amount, ident in wait_for: wait.wait() assert search_for_item( echo_app.raiden.wal.storage.get_events(), EventPaymentReceivedSuccess, { "amount": amount, "identifier": ident, "initiator": sender, "token_network_registry_address": registry_address, }, ) echo_node.stop()
def test_echo_node_lottery(token_addresses, raiden_chain, network_wait): app0, app1, app2, app3, echo_app, app4, app5, app6 = raiden_chain address_to_app = {app.raiden.address: app for app in raiden_chain} token_address = token_addresses[0] echo_api = RaidenAPI(echo_app.raiden) echo_node = EchoNode(echo_api, token_address) echo_node.ready.wait(timeout=30) assert echo_node.ready.is_set() transfer_timeout = 10 # Let 6 participants enter the pool amount = 7 for num, app in enumerate([app0, app1, app2, app3, app4, app5]): identifier = 100 * num with watch_for_unlock_failures(*raiden_chain): transfer_and_await( app=app, token_address=token_address, target=echo_app.raiden.address, amount=amount, identifier=identifier, timeout=transfer_timeout, ) # test duplicated identifier + amount is ignored with watch_for_unlock_failures(*raiden_chain): transfer_and_await( app=app5, token_address=token_address, target=echo_app.raiden.address, amount=amount, identifier=500, # app5 used this identifier before timeout=transfer_timeout, ) # test pool size querying pool_query_identifier = 77 # unused identifier different from previous one with watch_for_unlock_failures(*raiden_chain): transfer_and_await( app=app5, token_address=token_address, target=echo_app.raiden.address, amount=amount, identifier=pool_query_identifier, timeout=transfer_timeout, ) # fill the pool with watch_for_unlock_failures(*raiden_chain): transfer_and_await( app=app6, token_address=token_address, target=echo_app.raiden.address, amount=amount, identifier=600, timeout=transfer_timeout, ) def get_echoed_transfer(sent_transfer) -> Optional[EventPaymentReceivedSuccess]: """For a given transfer sent to echo node, get the corresponding echoed transfer""" app = address_to_app[sent_transfer.initiator] events = RaidenAPI(app.raiden).get_raiden_events_payment_history( token_address=token_address ) for event in events: if not type(event) == EventPaymentReceivedSuccess: continue assert isinstance(event, EventPaymentReceivedSuccess), MYPY_ANNOTATION if not ( event.initiator == echo_app.raiden.address and event.identifier == sent_transfer.identifier + event.amount ): continue return event return None def received_events_when_len(size: int) -> Optional[List[EventPaymentReceivedSuccess]]: """Return transfers received from echo_node when there's size transfers""" received_events = [] # Check that payout was generated and pool_size_query answered for handled_transfer in echo_node.seen_transfers: event = get_echoed_transfer(handled_transfer) if not event: continue received_events.append(event) log.debug( "Checking number of received events", received_events=received_events, expected_size=size, actual_size=len(received_events), seen_transfers=echo_node.seen_transfers, received_transfers=received_events, ) if len(received_events) == size: return received_events return None # wait for the expected echoed transfers to be handled received = wait_until(func=lambda: received_events_when_len(2), wait_for=network_wait) assert received received.sort(key=lambda transfer: transfer.amount) pool_query = received[0] assert pool_query.amount == 6 assert pool_query.identifier == pool_query_identifier + 6 winning_transfer = received[1] assert winning_transfer.initiator == echo_app.raiden.address assert winning_transfer.amount == 49 assert (winning_transfer.identifier - 49) % 10 == 0 echo_node.stop()
def test_secret_revealed_on_chain(raiden_chain, deposit, settle_timeout, token_addresses, retry_interval_initial): """ A node must reveal the secret on-chain if it's known and the channel is closed. """ app0, app1, app2 = raiden_chain token_address = token_addresses[0] token_network_address = views.get_token_network_address_by_token_address( views.state_from_app(app0), app0.raiden.default_registry.address, token_address) assert token_network_address amount = 10 identifier = 1 target = app2.raiden.address secret, secrethash = factories.make_secret_with_hash() # Reveal the secret, but do not unlock it off-chain app1_hold_event_handler = app1.raiden.raiden_event_handler app1_hold_event_handler.hold_unlock_for(secrethash=secrethash) app0.raiden.start_mediated_transfer_with_secret( token_network_address=token_network_address, amount=amount, target=target, identifier=identifier, secret=secret, ) with watch_for_unlock_failures(*raiden_chain), block_offset_timeout( app0.raiden): wait_for_state_change(app2.raiden, ReceiveSecretReveal, {"secrethash": secrethash}, retry_interval_initial) channel_state2_1 = get_channelstate(app2, app1, token_network_address) pending_lock = channel_state2_1.partner_state.secrethashes_to_unlockedlocks.get( secrethash) msg = "The lock must be registered in unlocked locks since the secret is known" assert pending_lock is not None, msg # The channels are out-of-sync. app1 has sent the unlock, however we are # intercepting it and app2 has not received the updated balance proof # Close the channel. This must register the secret on chain balance_proof = channel_state2_1.partner_state.balance_proof assert isinstance(balance_proof, BalanceProofSignedState) channel_close_event = ContractSendChannelClose( canonical_identifier=channel_state2_1.canonical_identifier, balance_proof=balance_proof, triggered_by_block_hash=app0.raiden.rpc_client. blockhash_from_blocknumber(BLOCK_ID_LATEST), ) current_state = app2.raiden.wal.state_manager.current_state app2.raiden.raiden_event_handler.on_raiden_events( raiden=app2.raiden, chain_state=current_state, events=[channel_close_event]) settle_expiration = (app0.raiden.rpc_client.block_number() + settle_timeout + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS) app0.raiden.proxy_manager.client.wait_until_block( target_block_number=settle_expiration) # TODO: # - assert on the transferred amounts on-chain (for settle and unlock) # The channel app0-app1 should continue with the protocol off-chain, once # the secret is released on-chain by app2 assert_synced_channel_state(token_network_address, app0, deposit - amount, [], app1, deposit + amount, []) with watch_for_unlock_failures(*raiden_chain), gevent.Timeout(10): wait_for_state_change( app2.raiden, ContractReceiveSecretReveal, {"secrethash": secrethash}, retry_interval_initial, )
def test_api_payments(api_server_test_instance: APIServer, raiden_network, token_addresses, deposit): _, app1 = raiden_network amount = 100 identifier = 42 token_address = token_addresses[0] target_address = app1.raiden.address our_address = api_server_test_instance.rest_api.raiden_api.address payment = { "initiator_address": to_checksum_address(our_address), "target_address": to_checksum_address(target_address), "token_address": to_checksum_address(token_address), "amount": str(amount), "identifier": str(identifier), } # Test a normal payment request = grequests.post( api_url_for( api_server_test_instance, "token_target_paymentresource", token_address=to_checksum_address(token_address), target_address=to_checksum_address(target_address), ), json={ "amount": str(amount), "identifier": str(identifier) }, ) with watch_for_unlock_failures(*raiden_network): response = request.send().response assert_proper_response(response) json_response = get_json_response(response) assert_payment_secret_and_hash(json_response, payment) # Test a payment without providing an identifier payment["amount"] = "1" request = grequests.post( api_url_for( api_server_test_instance, "token_target_paymentresource", token_address=to_checksum_address(token_address), target_address=to_checksum_address(target_address), ), json={"amount": "1"}, ) with watch_for_unlock_failures(*raiden_network): response = request.send().response assert_proper_response(response) json_response = get_json_response(response) assert_payment_secret_and_hash(json_response, payment) # Test that trying out a payment with an amount higher than what is available returns an error payment["amount"] = str(deposit) request = grequests.post( api_url_for( api_server_test_instance, "token_target_paymentresource", token_address=to_checksum_address(token_address), target_address=to_checksum_address(target_address), ), json={"amount": str(deposit)}, ) response = request.send().response assert_proper_response(response, status_code=HTTPStatus.CONFLICT) # Test that querying the internal events resource works limit = 5 request = grequests.get( api_url_for(api_server_test_instance, "raideninternaleventsresource", limit=limit, offset=0)) response = request.send().response assert_proper_response(response) events = response.json() assert len(events) == limit assert all("TimestampedEvent" in event for event in events)
def test_api_payments_with_lock_timeout(api_server_test_instance: APIServer, raiden_network, token_addresses): _, app1 = raiden_network amount = 100 identifier = 42 token_address = token_addresses[0] target_address = app1.raiden.address number_of_nodes = 2 reveal_timeout = number_of_nodes * 4 + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS settle_timeout = 39 # try lock_timeout = reveal_timeout - should not work request = grequests.post( api_url_for( api_server_test_instance, "token_target_paymentresource", token_address=to_checksum_address(token_address), target_address=to_checksum_address(target_address), ), json={ "amount": str(amount), "identifier": str(identifier), "lock_timeout": str(reveal_timeout), }, ) response = request.send().response assert_response_with_error(response, status_code=HTTPStatus.CONFLICT) # try lock_timeout = reveal_timeout * 2 - should work. request = grequests.post( api_url_for( api_server_test_instance, "token_target_paymentresource", token_address=to_checksum_address(token_address), target_address=to_checksum_address(target_address), ), json={ "amount": str(amount), "identifier": str(identifier), "lock_timeout": str(2 * reveal_timeout), }, ) with watch_for_unlock_failures(*raiden_network): response = request.send().response assert_proper_response(response, status_code=HTTPStatus.OK) # try lock_timeout = settle_timeout - should work. request = grequests.post( api_url_for( api_server_test_instance, "token_target_paymentresource", token_address=to_checksum_address(token_address), target_address=to_checksum_address(target_address), ), json={ "amount": str(amount), "identifier": str(identifier), "lock_timeout": str(settle_timeout), }, ) response = request.send().response assert_proper_response(response, status_code=HTTPStatus.OK) # try lock_timeout = settle_timeout+1 - should not work. request = grequests.post( api_url_for( api_server_test_instance, "token_target_paymentresource", token_address=to_checksum_address(token_address), target_address=to_checksum_address(target_address), ), json={ "amount": amount, "identifier": identifier, "lock_timeout": settle_timeout + 1 }, ) response = request.send().response assert_response_with_error(response, status_code=HTTPStatus.CONFLICT)
def test_api_payments_with_resolver( api_server_test_instance: APIServer, raiden_network, token_addresses, resolvers, # pylint: disable=unused-argument ): _, app1 = raiden_network amount = 100 identifier = 42 token_address = token_addresses[0] target_address = app1.raiden.address secret = factories.make_secret() secret_hash = sha256_secrethash(secret) our_address = api_server_test_instance.rest_api.raiden_api.address payment = { "initiator_address": to_checksum_address(our_address), "target_address": to_checksum_address(target_address), "token_address": to_checksum_address(token_address), "amount": str(amount), "identifier": str(identifier), } # payment with secret_hash when both resolver and initiator don't have the secret request = grequests.post( api_url_for( api_server_test_instance, "token_target_paymentresource", token_address=to_checksum_address(token_address), target_address=to_checksum_address(target_address), ), json={ "amount": str(amount), "identifier": str(identifier), "secret_hash": encode_hex(secret_hash), }, ) response = request.send().response assert_proper_response(response, status_code=HTTPStatus.CONFLICT) assert payment == payment # payment with secret where the resolver doesn't have the secret. Should work. request = grequests.post( api_url_for( api_server_test_instance, "token_target_paymentresource", token_address=to_checksum_address(token_address), target_address=to_checksum_address(target_address), ), json={ "amount": str(amount), "identifier": str(identifier), "secret": encode_hex(secret) }, ) response = request.send().response assert_proper_response(response, status_code=HTTPStatus.OK) assert payment == payment # payment with secret_hash where the resolver has the secret. Should work. secret = Secret( decode_hex( "0x2ff886d47b156de00d4cad5d8c332706692b5b572adfe35e6d2f65e92906806e" )) secret_hash = sha256_secrethash(secret) request = grequests.post( api_url_for( api_server_test_instance, "token_target_paymentresource", token_address=to_checksum_address(token_address), target_address=to_checksum_address(target_address), ), json={ "amount": str(amount), "identifier": str(identifier), "secret_hash": encode_hex(secret_hash), }, ) with watch_for_unlock_failures(*raiden_network): response = request.send().response assert_proper_response(response, status_code=HTTPStatus.OK) assert payment == payment
def test_participant_selection(raiden_network, token_addresses): # pylint: disable=too-many-locals registry_address = raiden_network[0].raiden.default_registry.address one_to_n_address = raiden_network[0].raiden.default_one_to_n_address token_address = token_addresses[0] # connect the first node - this will register the token and open the first channel # Since there is no other nodes available to connect to this call will do nothing more RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=TokenAmount(100)) # Test invalid argument values with pytest.raises(InvalidAmount): RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=TokenAmount(-1)) with pytest.raises(InvalidAmount): RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=TokenAmount(100), joinable_funds_target=2, ) with pytest.raises(InvalidAmount): RaidenAPI(raiden_network[0].raiden).token_network_connect( registry_address=registry_address, token_address=token_address, funds=TokenAmount(100), joinable_funds_target=-1, ) # Call the connect endpoint for all but the first node connect_greenlets = [ gevent.spawn( RaidenAPI(app.raiden).token_network_connect, registry_address, token_address, 100) for app in raiden_network[1:] ] gevent.wait(connect_greenlets) token_network_registry_address = views.get_token_network_address_by_token_address( views.state_from_raiden(raiden_network[0].raiden), token_network_registry_address=registry_address, token_address=token_address, ) connection_managers = [ app.raiden.connection_manager_for_token_network( token_network_registry_address) for app in raiden_network ] unsaturated_connection_managers = connection_managers[:] exception = AssertionError("Unsaturated connection managers", unsaturated_connection_managers) with gevent.Timeout(120, exception): while unsaturated_connection_managers: for manager in unsaturated_connection_managers: if is_manager_saturated(manager, registry_address, token_address): unsaturated_connection_managers.remove(manager) gevent.sleep(1) assert saturated_count(connection_managers, registry_address, token_address) == len(connection_managers) # ensure unpartitioned network for app in raiden_network: node_state = views.state_from_raiden(app.raiden) network_state = views.get_token_network_by_token_address( node_state, registry_address, token_address) assert network_state is not None for target in raiden_network: if target.raiden.address == app.raiden.address: continue _, routes, _ = routing.get_best_routes( chain_state=node_state, token_network_address=network_state.address, one_to_n_address=one_to_n_address, from_address=app.raiden.address, to_address=target.raiden.address, amount=PaymentAmount(1), previous_address=None, pfs_config=None, privkey=b"", # not used if pfs is not configured ) assert routes is not None # create a transfer to the leaving node, so we have a channel to settle for app in raiden_network: sender = app.raiden sender_channel = next( (channel_state for channel_state in RaidenAPI( sender).get_channel_list(registry_address=registry_address, token_address=token_address) if channel_state.our_state.contract_balance > 0 and channel_state.partner_state.contract_balance > 0), None, ) # choose a fully funded channel from sender if sender_channel: break assert sender_channel registry_address = sender.default_registry.address receiver = next( app.raiden for app in raiden_network if app.raiden.address == sender_channel.partner_state.address) # assert there is a direct channel receiver -> sender (vv) receiver_channel = RaidenAPI(receiver).get_channel_list( registry_address=registry_address, token_address=token_address, partner_address=sender.address, ) assert len(receiver_channel) == 1 with gevent.Timeout(30, exception=ValueError("partner not reachable")): waiting.wait_for_healthy(sender, receiver.address, PaymentAmount(1)) with watch_for_unlock_failures(*raiden_network): amount = PaymentAmount(1) RaidenAPI(sender).transfer_and_wait(registry_address, token_address, amount, receiver.address, transfer_timeout=10) with gevent.Timeout( 30, exception=ValueError( "timeout while waiting for incoming transaction")): wait_for_transaction(receiver, registry_address, token_address, sender.address) # test `leave()` method connection_manager = connection_managers[0] timeout = (sender_channel.settle_timeout * estimate_blocktime(connection_manager.raiden.rpc_client) * 10) assert timeout > 0 channels = views.list_channelstate_for_tokennetwork( chain_state=views.state_from_raiden(connection_manager.raiden), token_network_registry_address=registry_address, token_address=token_address, ) channel_identifiers = [channel.identifier for channel in channels] with gevent.Timeout( timeout, exception=ValueError("timeout while waiting for leave")): # sender leaves the network RaidenAPI(sender).token_network_leave(registry_address, token_address) with gevent.Timeout(timeout, exception=ValueError( f"Channels didnt get settled after {timeout}")): waiting.wait_for_settle( raiden=connection_manager.raiden, token_network_registry_address=registry_address, token_address=token_address, channel_ids=channel_identifiers, retry_timeout=0.1, )
def test_payment_statuses_are_restored( # pylint: disable=unused-argument raiden_network, token_addresses, network_wait): """ Test that when the Raiden is restarted, the dictionary of `targets_to_identifiers_to_statuses` is populated before the transport is started. This should happen because if a client gets restarted during a transfer cycle, once restarted, the client will proceed with the cycle until the transfer is successfully sent. However, the dictionary `targets_to_identifiers_to_statuses` will not contain the payment identifiers that were originally registered when the previous client started the transfers. Related issue: https://github.com/raiden-network/raiden/issues/3432 """ app0, app1 = raiden_network token_address = token_addresses[0] chain_state = views.state_from_app(app0) token_network_registry_address = app0.raiden.default_registry.address token_network_address = views.get_token_network_address_by_token_address( chain_state, token_network_registry_address, token_address) # make a few transfers from app0 to app1 amount = 1 spent_amount = TokenAmount(7) for identifier in range(spent_amount): # Make sure the transfer is not completed secret = make_secret(identifier) app0.raiden.raiden_event_handler.hold(SendSecretReveal, {"secret": secret}) identifier = identifier + 1 payment_status = app0.raiden.mediated_transfer_async( token_network_address=token_network_address, amount=amount, target=app1.raiden.address, identifier=identifier, secret=secret, ) assert payment_status.payment_identifier == identifier app0_restart = App( config=app0.config, rpc_client=app0.raiden.rpc_client, proxy_manager=app0.raiden.proxy_manager, query_start_block=BlockNumber(0), default_registry=app0.raiden.default_registry, default_secret_registry=app0.raiden.default_secret_registry, default_service_registry=app0.raiden.default_service_registry, default_one_to_n_address=app0.raiden.default_one_to_n_address, default_msc_address=app0.raiden.default_msc_address, transport=MatrixTransport(app0.raiden.config["transport"]["matrix"]), raiden_event_handler=RaidenEventHandler(), message_handler=MessageHandler(), routing_mode=RoutingMode.PRIVATE, ) app0.stop() del app0 # from here on the app0_restart should be used # stop app1 to make sure that we don't complete the transfers before our checks app1.stop() app0_restart.start() # Check that the payment statuses were restored properly after restart for identifier in range(spent_amount): identifier = PaymentID(identifier + 1) mapping = app0_restart.raiden.targets_to_identifiers_to_statuses status = mapping[app1.raiden.address][identifier] assert status.amount == 1 assert status.payment_identifier == identifier assert status.token_network_address == token_network_address app1.start() # now that our checks are done start app1 again with watch_for_unlock_failures(*raiden_network): waiting.wait_for_healthy(app0_restart.raiden, app1.raiden.address, network_wait) waiting.wait_for_payment_balance( raiden=app1.raiden, token_network_registry_address=token_network_registry_address, token_address=token_address, partner_address=app0_restart.raiden.address, target_address=app1.raiden.address, target_balance=spent_amount, retry_timeout=network_wait, ) # Check that payments are completed after both nodes come online after restart for identifier in range(spent_amount): assert raiden_events_search_for_item( app0_restart.raiden, EventPaymentSentSuccess, { "identifier": identifier + 1, "amount": 1 }, )
def test_payment_events_endpoints(api_server_test_instance: APIServer, raiden_network, token_addresses): app0, app1, app2 = raiden_network amount1 = PaymentAmount(10) identifier1 = PaymentID(42) secret1, secrethash1 = factories.make_secret_with_hash() token_address = token_addresses[0] app0_address = app0.raiden.address target1_address = app1.raiden.address target2_address = app2.raiden.address app1_server = prepare_api_server(app1) app2_server = prepare_api_server(app2) # app0 is sending tokens to target 1 request = grequests.post( api_url_for( api_server_test_instance, "token_target_paymentresource", token_address=to_checksum_address(token_address), target_address=to_checksum_address(target1_address), ), json={ "amount": str(amount1), "identifier": str(identifier1), "secret": to_hex(secret1) }, ) request.send() # app0 is sending some tokens to target 2 identifier2 = PaymentID(43) amount2 = PaymentAmount(10) secret2, secrethash2 = factories.make_secret_with_hash() request = grequests.post( api_url_for( api_server_test_instance, "token_target_paymentresource", token_address=to_checksum_address(token_address), target_address=to_checksum_address(target2_address), ), json={ "amount": str(amount2), "identifier": str(identifier2), "secret": to_hex(secret2) }, ) request.send() # target1 also sends some tokens to target 2 identifier3 = PaymentID(44) amount3 = PaymentAmount(5) secret3, secrethash3 = factories.make_secret_with_hash() request = grequests.post( api_url_for( app1_server, "token_target_paymentresource", token_address=to_checksum_address(token_address), target_address=to_checksum_address(target2_address), ), json={ "amount": str(amount3), "identifier": str(identifier3), "secret": to_hex(secret3) }, ) request.send() timeout = block_offset_timeout( app2.raiden, "Waiting for transfer received success in the WAL timed out") with watch_for_unlock_failures(*raiden_network), timeout: result = wait_for_received_transfer_result( app1.raiden, identifier1, amount1, app1.raiden.alarm.sleep_time, secrethash1) msg = f"Unexpected transfer result: {str(result)}" assert result == TransferWaitResult.UNLOCKED, msg result = wait_for_received_transfer_result( app2.raiden, identifier2, amount2, app2.raiden.alarm.sleep_time, secrethash2) msg = f"Unexpected transfer result: {str(result)}" assert result == TransferWaitResult.UNLOCKED, msg result = wait_for_received_transfer_result( app2.raiden, identifier3, amount3, app2.raiden.alarm.sleep_time, secrethash3) msg = f"Unexpected transfer result: {str(result)}" assert result == TransferWaitResult.UNLOCKED, msg # test endpoint without (partner and token) for sender request = grequests.get( api_url_for(api_server_test_instance, "paymentresource")) with watch_for_unlock_failures(*raiden_network): response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert must_have_event( json_response, { "event": "EventPaymentSentSuccess", "identifier": str(identifier1), "target": to_checksum_address(target1_address), "token_address": to_checksum_address(token_address), }, ) assert must_have_event( json_response, { "event": "EventPaymentSentSuccess", "identifier": str(identifier2), "target": to_checksum_address(target2_address), "token_address": to_checksum_address(token_address), }, ) # test endpoint without (partner and token) for target1 request = grequests.get(api_url_for(app1_server, "paymentresource")) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert must_have_event( json_response, { "event": "EventPaymentReceivedSuccess", "identifier": str(identifier1), "token_address": to_checksum_address(token_address), }, ) assert must_have_event( json_response, { "event": "EventPaymentSentSuccess", "identifier": str(identifier3), "token_address": to_checksum_address(token_address), }, ) # test endpoint without (partner and token) for target2 request = grequests.get(api_url_for(app2_server, "paymentresource")) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert must_have_event( json_response, { "event": "EventPaymentReceivedSuccess", "identifier": str(identifier2), "token_address": to_checksum_address(token_address), }, ) assert must_have_event( json_response, { "event": "EventPaymentReceivedSuccess", "identifier": str(identifier3), "token_address": to_checksum_address(token_address), }, ) # test endpoint without partner for app0 request = grequests.get( api_url_for(api_server_test_instance, "token_paymentresource", token_address=token_address)) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert must_have_event( json_response, { "event": "EventPaymentSentSuccess", "identifier": str(identifier1), "target": to_checksum_address(target1_address), "token_address": to_checksum_address(token_address), }, ) assert must_have_event( json_response, { "event": "EventPaymentSentSuccess", "identifier": str(identifier2), "target": to_checksum_address(target2_address), "token_address": to_checksum_address(token_address), }, ) # test endpoint without partner for app0 but with limit/offset to get only first request = grequests.get( api_url_for( api_server_test_instance, "token_paymentresource", token_address=token_address, limit=1, offset=0, )) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert must_have_event( json_response, { "event": "EventPaymentSentSuccess", "identifier": str(identifier1), "target": to_checksum_address(target1_address), "token_address": to_checksum_address(token_address), }, ) assert len(json_response) == 1 # test endpoint without partner for app0 but with limit/offset to get only second request = grequests.get( api_url_for( api_server_test_instance, "token_paymentresource", token_address=token_address, limit=1, offset=1, )) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert must_have_event( json_response, { "event": "EventPaymentSentSuccess", "identifier": str(identifier2), "target": to_checksum_address(target2_address), "token_address": to_checksum_address(token_address), }, ) # test endpoint without partner for target1 request = grequests.get( api_url_for(app1_server, "token_paymentresource", token_address=token_address)) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert must_have_events( json_response, { "event": "EventPaymentReceivedSuccess", "identifier": str(identifier1), "token_address": to_checksum_address(token_address), }, { "event": "EventPaymentSentSuccess", "identifier": str(identifier3), "target": to_checksum_address(target2_address), "token_address": to_checksum_address(token_address), }, ) # test endpoint without partner for target2 request = grequests.get( api_url_for(app2_server, "token_paymentresource", token_address=token_address)) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert must_have_events( json_response, { "event": "EventPaymentReceivedSuccess", "identifier": str(identifier2), "token_address": to_checksum_address(token_address), }, { "event": "EventPaymentReceivedSuccess", "identifier": str(identifier3), "token_address": to_checksum_address(token_address), }, ) # test endpoint for token and partner for app0 request = grequests.get( api_url_for( api_server_test_instance, "token_target_paymentresource", token_address=token_address, target_address=target1_address, )) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert must_have_event( json_response, { "event": "EventPaymentSentSuccess", "identifier": str(identifier1), "target": to_checksum_address(target1_address), "token_address": to_checksum_address(token_address), }, ) assert not must_have_event( json_response, { "event": "EventPaymentSentSuccess", "identifier": str(identifier2), "target": to_checksum_address(target2_address), "token_address": to_checksum_address(token_address), }, ) # test endpoint for token and partner for target1. Check both partners # to see that filtering works correctly request = grequests.get( api_url_for( app1_server, "token_target_paymentresource", token_address=token_address, target_address=target2_address, )) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert must_have_event( json_response, { "event": "EventPaymentSentSuccess", "identifier": str(identifier3), "target": to_checksum_address(target2_address), "token_address": to_checksum_address(token_address), }, ) assert not must_have_event( response, { "event": "EventPaymentReceivedSuccess", "identifier": str(identifier1), "token_address": to_checksum_address(token_address), }, ) request = grequests.get( api_url_for( app1_server, "token_target_paymentresource", token_address=token_address, target_address=target1_address, )) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert len(json_response) == 0 # test endpoint for token and partner for target2 request = grequests.get( api_url_for( app2_server, "token_target_paymentresource", token_address=token_address, target_address=app0_address, )) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert must_have_events( json_response, { "event": "EventPaymentReceivedSuccess", "identifier": str(identifier2), "token_address": to_checksum_address(token_address), }, ) assert not must_have_event( json_response, { "event": "EventPaymentReceivedSuccess", "identifier": str(identifier1), "token_address": to_checksum_address(token_address), }, ) assert not must_have_event( json_response, { "event": "EventPaymentReceivedSuccess", "identifier": str(identifier3), "token_address": to_checksum_address(token_address), }, ) request = grequests.get( api_url_for( app2_server, "token_target_paymentresource", token_address=token_address, target_address=target1_address, )) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert must_have_events( json_response, { "event": "EventPaymentReceivedSuccess", "identifier": str(identifier3), "token_address": to_checksum_address(token_address), }, ) assert not must_have_event( json_response, { "event": "EventPaymentReceivedSuccess", "identifier": str(identifier2), "token_address": to_checksum_address(token_address), }, ) assert not must_have_event( json_response, { "event": "EventPaymentReceivedSuccess", "identifier": str(identifier1), "token_address": to_checksum_address(token_address), }, ) # also add a test for filtering by wrong token address request = grequests.get( api_url_for( app2_server, "token_target_paymentresource", token_address=target1_address, target_address=target1_address, )) response = request.send().response assert_proper_response(response, HTTPStatus.OK) json_response = get_json_response(response) assert len(json_response) == 0 app1_server.stop() app2_server.stop()
def test_send_queued_messages( # pylint: disable=unused-argument raiden_network, deposit, token_addresses, network_wait): """Test re-sending of undelivered messages on node restart""" app0, app1 = raiden_network token_address = token_addresses[0] chain_state = views.state_from_app(app0) token_network_registry_address = app0.raiden.default_registry.address token_network_address = views.get_token_network_address_by_token_address( chain_state, token_network_registry_address, token_address) assert token_network_address number_of_transfers = 7 amount_per_transfer = 1 total_transferred_amount = TokenAmount(amount_per_transfer * number_of_transfers) # Make sure none of the transfers will be sent before the restart transfers = [] for secret_seed in range(number_of_transfers): secret = make_secret(secret_seed) secrethash = sha256_secrethash(secret) transfers.append((create_default_identifier(), amount_per_transfer, secret, secrethash)) app0.raiden.raiden_event_handler.hold( SendLockedTransfer, {"transfer": { "lock": { "secrethash": secrethash } }}) for identifier, amount, secret, _ in transfers: app0.raiden.mediated_transfer_async( token_network_address=token_network_address, amount=amount, target=app1.raiden.address, identifier=identifier, secret=secret, ) app0.stop() # Restart the app. The pending transfers must be processed. new_transport = MatrixTransport(app0.raiden.config["transport"]["matrix"]) raiden_event_handler = RaidenEventHandler() message_handler = MessageHandler() app0_restart = App( config=app0.config, rpc_client=app0.raiden.rpc_client, proxy_manager=app0.raiden.proxy_manager, query_start_block=BlockNumber(0), default_registry=app0.raiden.default_registry, default_secret_registry=app0.raiden.default_secret_registry, default_service_registry=app0.raiden.default_service_registry, default_one_to_n_address=app0.raiden.default_one_to_n_address, default_msc_address=app0.raiden.default_msc_address, transport=new_transport, raiden_event_handler=raiden_event_handler, message_handler=message_handler, routing_mode=RoutingMode.PRIVATE, ) del app0 app0_restart.start() # XXX: There is no synchronization among the app and the test, so it is # possible between `start` and the check bellow that some of the transfers # have completed, making it flaky. # # Make sure the transfers are in the queue and fail otherwise. # chain_state = views.state_from_raiden(app0_restart.raiden) # for _, _, _, secrethash in transfers: # msg = "The secrethashes of the pending transfers must be in the queue after a restart." # assert secrethash in chain_state.payment_mapping.secrethashes_to_task, msg with watch_for_unlock_failures(*raiden_network): exception = RuntimeError( "Timeout while waiting for balance update for app0") with gevent.Timeout(20, exception=exception): waiting.wait_for_payment_balance( raiden=app0_restart.raiden, token_network_registry_address=token_network_registry_address, token_address=token_address, partner_address=app1.raiden.address, target_address=app1.raiden.address, target_balance=total_transferred_amount, retry_timeout=network_wait, ) exception = RuntimeError( "Timeout while waiting for balance update for app1") with gevent.Timeout(20, exception=exception): waiting.wait_for_payment_balance( raiden=app1.raiden, token_network_registry_address=token_network_registry_address, token_address=token_address, partner_address=app0_restart.raiden.address, target_address=app1.raiden.address, target_balance=total_transferred_amount, retry_timeout=network_wait, ) assert_synced_channel_state( token_network_address, app0_restart, deposit - total_transferred_amount, [], app1, deposit + total_transferred_amount, [], ) new_transport.stop()
def test_send_queued_messages_after_restart( # pylint: disable=unused-argument raiden_network: List[RaidenService], restart_node: RestartNode, deposit: TokenAmount, token_addresses: List[TokenAddress], network_wait: float, ): """Test re-sending of undelivered messages on node restart""" app0, app1 = raiden_network token_address = token_addresses[0] chain_state = views.state_from_raiden(app0) token_network_registry_address = app0.default_registry.address token_network_address = views.get_token_network_address_by_token_address( chain_state, token_network_registry_address, token_address) assert token_network_address number_of_transfers = 7 amount_per_transfer = PaymentAmount(1) total_transferred_amount = TokenAmount(amount_per_transfer * number_of_transfers) # Make sure none of the transfers will be sent before the restart transfers = [] for secret_seed in range(number_of_transfers): secret = make_secret(secret_seed) secrethash = sha256_secrethash(secret) transfers.append((create_default_identifier(), amount_per_transfer, secret, secrethash)) assert isinstance(app0.raiden_event_handler, HoldRaidenEventHandler) # for mypy app0.raiden_event_handler.hold( SendLockedTransfer, {"transfer": { "lock": { "secrethash": secrethash } }}) for identifier, amount, secret, _ in transfers: app0.mediated_transfer_async( token_network_address=token_network_address, amount=amount, target=TargetAddress(app1.address), identifier=identifier, secret=secret, ) app0.stop() # Restart the app. The pending transfers must be processed. new_transport = MatrixTransport(config=app0.config.transport, environment=app0.config.environment_type) raiden_event_handler = RaidenEventHandler() message_handler = MessageHandler() app0_restart = RaidenService( config=app0.config, rpc_client=app0.rpc_client, proxy_manager=app0.proxy_manager, query_start_block=BlockNumber(0), raiden_bundle=RaidenBundle( app0.default_registry, app0.default_secret_registry, ), services_bundle=app0.default_services_bundle, transport=new_transport, raiden_event_handler=raiden_event_handler, message_handler=message_handler, routing_mode=RoutingMode.PRIVATE, ) del app0 restart_node(app0_restart) # XXX: There is no synchronization among the app and the test, so it is # possible between `start` and the check below that some of the transfers # have completed, making it flaky. # # Make sure the transfers are in the queue and fail otherwise. chain_state = views.state_from_raiden(app0_restart) for _, _, _, secrethash in transfers: msg = "The secrethashes of the pending transfers must be in the queue after a restart." assert secrethash in chain_state.payment_mapping.secrethashes_to_task, msg timeout = block_offset_timeout( app1, "Timeout waiting for balance update of app0") with watch_for_unlock_failures(*raiden_network), timeout: waiting.wait_for_payment_balance( raiden=app0_restart, token_network_registry_address=token_network_registry_address, token_address=token_address, partner_address=app1.address, target_address=app1.address, target_balance=total_transferred_amount, retry_timeout=network_wait, ) timeout.exception_to_throw = ValueError( "Timeout waiting for balance update of app1") waiting.wait_for_payment_balance( raiden=app1, token_network_registry_address=token_network_registry_address, token_address=token_address, partner_address=app0_restart.address, target_address=app1.address, target_balance=total_transferred_amount, retry_timeout=network_wait, ) assert_synced_channel_state( token_network_address, app0_restart, Balance(deposit - total_transferred_amount), [], app1, Balance(deposit + total_transferred_amount), [], ) new_transport.stop()