def test_create_monitoring_request(raiden_network, token_addresses): 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=chain_state, token_network_registry_address=token_network_registry_address, token_address=token_address, ) assert token_network_address payment_identifier = create_default_identifier() transfer( initiator_app=app1, target_app=app0, token_address=token_address, amount=PaymentAmount(1), identifier=payment_identifier, ) chain_state = views.state_from_raiden(app0.raiden) channel_state = views.get_channelstate_by_token_network_and_partner( chain_state, token_network_address, app1.raiden.address) assert channel_state balance_proof = cast(BalanceProofSignedState, channel_state.partner_state.balance_proof) api = RaidenAPI(app0.raiden) request = api.create_monitoring_request(balance_proof=balance_proof, reward_amount=TokenAmount(1)) assert request as_dict = DictSerializer.serialize(request) from_dict = DictSerializer.deserialize(as_dict) assert DictSerializer.serialize(from_dict) == as_dict
def test_recovery_happy_case(raiden_network, restart_node, number_of_nodes, deposit, token_addresses, network_wait): app0, app1, app2 = 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 # make a few transfers from app0 to app2 amount = PaymentAmount(1) spent_amount = deposit - 2 for identifier in range(spent_amount): transfer_and_assert_path( path=raiden_network, token_address=token_address, amount=amount, identifier=PaymentID(identifier), timeout=network_wait * number_of_nodes, ) app0.stop() waiting.wait_for_network_state(app1.raiden, app0.raiden.address, NetworkState.UNREACHABLE, network_wait) restart_node(app0) assert_synced_channel_state(token_network_address, app0, deposit - spent_amount, [], app1, deposit + spent_amount, []) assert_synced_channel_state(token_network_address, app1, deposit - spent_amount, [], app2, deposit + spent_amount, []) # wait for the nodes' healthcheck to update the network statuses waiting.wait_for_healthy(app0.raiden, app1.raiden.address, network_wait) waiting.wait_for_healthy(app1.raiden, app0.raiden.address, network_wait) transfer_and_assert_path( path=raiden_network[::-1], token_address=token_address, amount=amount, identifier=create_default_identifier(), timeout=network_wait * number_of_nodes, ) transfer_and_assert_path( path=raiden_network, token_address=token_address, amount=amount, identifier=create_default_identifier(), timeout=network_wait * number_of_nodes, ) assert_succeeding_transfer_invariants(token_network_address, app0, deposit - spent_amount, [], app1, deposit + spent_amount, []) assert_succeeding_transfer_invariants(token_network_address, app1, deposit - spent_amount, [], app2, deposit + spent_amount, [])
def test_send_queued_messages_after_restart( # pylint: disable=unused-argument raiden_network: List[App], 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_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 = 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.raiden_event_handler, HoldRaidenEventHandler) # for mypy 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=TargetAddress(app1.raiden.address), identifier=identifier, secret=secret, ) app0.stop() # Restart the app. The pending transfers must be processed. new_transport = MatrixTransport( config=app0.raiden.config.transport, environment=app0.raiden.config.environment_type) 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 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.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, Balance(deposit - total_transferred_amount), [], app1, Balance(deposit + total_transferred_amount), [], ) new_transport.stop()
def transfer_async( self, registry_address: TokenNetworkRegistryAddress, token_address: TokenAddress, amount: PaymentAmount, target: TargetAddress, identifier: PaymentID = None, secret: Secret = None, secrethash: SecretHash = None, lock_timeout: BlockTimeout = None, ) -> "PaymentStatus": current_state = views.state_from_raiden(self.raiden) token_network_registry_address = self.raiden.default_registry.address if not isinstance(amount, int): # pragma: no unittest raise InvalidAmount("Amount not a number") if Address(target) == self.address: raise SamePeerAddress("Address must be different than ours") if amount <= 0: raise InvalidAmount("Amount negative") if amount > UINT256_MAX: raise InvalidAmount("Amount too large") if not is_binary_address(token_address): raise InvalidBinaryAddress("token address is not valid.") if token_address not in views.get_token_identifiers( current_state, registry_address): raise UnknownTokenAddress("Token address is not known.") if not is_binary_address(target): raise InvalidBinaryAddress("target address is not valid.") valid_tokens = views.get_token_identifiers( views.state_from_raiden(self.raiden), registry_address) if token_address not in valid_tokens: raise UnknownTokenAddress("Token address is not known.") if secret is not None and not isinstance(secret, T_Secret): raise InvalidSecret("secret is not valid.") if secrethash is not None and not isinstance(secrethash, T_SecretHash): raise InvalidSecretHash("secrethash is not valid.") if identifier is None: identifier = create_default_identifier() if identifier <= 0: raise InvalidPaymentIdentifier( "Payment identifier cannot be 0 or negative") if identifier > UINT64_MAX: raise InvalidPaymentIdentifier("Payment identifier is too large") log.debug( "Initiating transfer", initiator=to_checksum_address(self.raiden.address), target=to_checksum_address(target), token=to_checksum_address(token_address), amount=amount, identifier=identifier, ) token_network_address = views.get_token_network_address_by_token_address( chain_state=current_state, token_network_registry_address=token_network_registry_address, token_address=token_address, ) if token_network_address is None: raise UnknownTokenAddress( f"Token {to_checksum_address(token_address)} is not registered " f"with the network {to_checksum_address(registry_address)}.") payment_status = self.raiden.mediated_transfer_async( token_network_address=token_network_address, amount=amount, target=target, identifier=identifier, secret=secret, secrethash=secrethash, lock_timeout=lock_timeout, ) return payment_status