def test_capacity_check( token_network_model: TokenNetwork, reachability_state: SimpleReachabilityContainer, addresses: List[Address], ): """ Test that the mediation fees are included in the capacity check """ # First get a path without mediation fees. This must return the shortest path: 4->1->0 paths = token_network_model.get_paths( source=addresses[4], target=addresses[0], value=PaymentAmount(35), max_paths=1, reachability_state=reachability_state, ) index_paths = [addresses_to_indexes(p.nodes, addresses) for p in paths] assert index_paths == [[4, 1, 0]] # New let's add mediation fees to the channel 0->1. model_with_fees = deepcopy(token_network_model) model_with_fees.G[addresses[1]][ addresses[0]]["view"].fee_schedule_sender.flat = 1 # The transfer from 4->1 must now include 1 Token for the mediation fee # which will be payed for the 1->0 channel in addition to the payment # value of 35. But 35 + 1 exceeds the capacity for channel 4->1, which is # 35. So we should now get the next best route instead. paths = model_with_fees.get_paths( source=addresses[4], target=addresses[0], value=PaymentAmount(35), max_paths=1, reachability_state=reachability_state, fee_penalty=0, ) index_paths = [addresses_to_indexes(p.nodes, addresses) for p in paths] assert index_paths == [[4, 1, 2, 0]]
def test_channel_withdraw( raiden_network: List[App], token_addresses: List[TokenAddress], deposit: TokenAmount, retry_timeout: float, ) -> None: """ Withdraw funds after a mediated transfer.""" alice_app, bob_app = raiden_network token_address = token_addresses[0] token_network_address = views.get_token_network_address_by_token_address( views.state_from_app(alice_app), alice_app.raiden.default_registry.address, token_address ) assert token_network_address token_proxy = bob_app.raiden.proxy_manager.token(token_address, BLOCK_ID_LATEST) bob_initial_balance = token_proxy.balance_of(bob_app.raiden.address) message_handler = WaitForMessage() bob_app.raiden.message_handler = message_handler alice_to_bob_amount = PaymentAmount(10) identifier = PaymentID(1) target = TargetAddress(bob_app.raiden.address) secret = factories.make_secret() payment_status = alice_app.raiden.start_mediated_transfer_with_secret( token_network_address=token_network_address, amount=alice_to_bob_amount, target=target, identifier=identifier, secret=secret, ) wait_for_unlock = bob_app.raiden.message_handler.wait_for_message( Unlock, {"payment_identifier": identifier} ) with block_offset_timeout(alice_app.raiden): wait_for_unlock.get() msg = ( f"transfer from {to_checksum_address(alice_app.raiden.address)} " f"to {to_checksum_address(bob_app.raiden.address)} failed." ) assert payment_status.payment_done.get(), msg total_withdraw = WithdrawAmount(deposit + alice_to_bob_amount) bob_alice_channel_state = get_channelstate(bob_app, alice_app, token_network_address) bob_app.raiden.withdraw( canonical_identifier=bob_alice_channel_state.canonical_identifier, total_withdraw=total_withdraw, ) waiting.wait_for_withdraw_complete( raiden=bob_app.raiden, canonical_identifier=bob_alice_channel_state.canonical_identifier, total_withdraw=total_withdraw, retry_timeout=retry_timeout, ) bob_balance_after_withdraw = token_proxy.balance_of(bob_app.raiden.address) assert bob_initial_balance + total_withdraw == bob_balance_after_withdraw
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_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_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_unfiltered_routes(raiden_network, token_addresses, settle_timeout, deposit): """ The transfer should proceed without triggering an assert. Transfers failed in networks where two or more paths to the destination are possible but they share same node as a first hop. """ app0, app1, app2, app3, app4 = raiden_network token = token_addresses[0] registry_address = app0.raiden.default_registry.address # Topology: # # 0 -> 1 -> 2 -> 4 # | ^ # +--> 3 ---+ app_channels = [(app0, app1), (app1, app2), (app1, app3), (app3, app4), (app2, app4)] open_and_wait_for_channels(app_channels, registry_address, token, deposit, settle_timeout) transfer( initiator_app=app0, target_app=app4, token_address=token, amount=PaymentAmount(1), identifier=PaymentID(1), )
def test_pfs_handler_handle_paymentsentsuccess_without_feedback_token(): ( raiden, pfs_handler, token_network_registry_address, token_network_address, route, _, ) = setup_pfs_handler_test(set_feedback_token=False) payment_id = make_payment_id() amount = PaymentAmount(123) target = TargetAddress(route[-1]) raiden.targets_to_identifiers_to_statuses[target][payment_id] = Mock() route_failed_event = EventPaymentSentSuccess( token_network_registry_address=token_network_registry_address, token_network_address=token_network_address, identifier=payment_id, amount=amount, target=TargetAddress(target), secret=make_secret(), route=route, ) with patch("raiden.raiden_event_handler.post_pfs_feedback" ) as pfs_feedback_handler: pfs_handler.on_raiden_events( raiden=raiden, chain_state=cast( ChainState, raiden.wal.state_manager.current_state), # type: ignore events=[route_failed_event], ) assert not pfs_feedback_handler.called
def test_receive_lockedtransfer_invalidnonce(raiden_network, number_of_nodes, deposit, token_addresses, reveal_timeout, network_wait): app0, app1, app2 = raiden_network 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 channel0 = get_channelstate(app0, app1, token_network_address) amount = 10 payment_identifier = PaymentID(1) secrethash = transfer( initiator_app=app0, target_app=app2, token_address=token_address, amount=PaymentAmount(10), identifier=payment_identifier, timeout=network_wait * number_of_nodes, ) repeated_nonce = Nonce(1) expiration = reveal_timeout * 2 mediated_transfer_message = LockedTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=make_message_identifier(), payment_identifier=payment_identifier, nonce=repeated_nonce, token_network_address=token_network_address, token=token_address, channel_identifier=channel0.identifier, transferred_amount=TokenAmount(amount), locked_amount=TokenAmount(amount), recipient=app1.raiden.address, locksroot=make_locksroot(), lock=Lock(amount=PaymentWithFeeAmount(amount), expiration=expiration, secrethash=UNIT_SECRETHASH), target=app2.raiden.address, initiator=app0.raiden.address, signature=EMPTY_SIGNATURE, metadata=Metadata(routes=[ RouteMetadata(route=[app1.raiden.address, app2.raiden.address]) ]), ) sign_and_inject(mediated_transfer_message, app0.raiden.signer, app1) with block_timeout_for_transfer_by_secrethash(app1.raiden, secrethash): wait_assert( assert_synced_channel_state, token_network_address, app0, deposit - amount, [], app1, deposit + amount, [], )
def test_api_channel_events(raiden_chain, token_addresses): app0, app1 = raiden_chain token_address = token_addresses[0] amount = PaymentAmount(30) transfer( initiator_app=app0, target_app=app1, token_address=token_address, amount=amount, identifier=PaymentID(1), ) app0_events = RaidenAPI(app0.raiden).get_blockchain_events_channel( token_address, app1.raiden.address) assert must_have_event(app0_events, {"event": ChannelEvent.DEPOSIT}) app0_events = app0.raiden.wal.storage.get_events() assert any( isinstance(event, EventPaymentSentSuccess) for event in app0_events) app1_events = app1.raiden.wal.storage.get_events() assert any( isinstance(event, EventPaymentReceivedSuccess) for event in app1_events) app1_events = RaidenAPI(app1.raiden).get_blockchain_events_channel( token_address, app0.raiden.address) assert must_have_event(app1_events, {"event": ChannelEvent.DEPOSIT})
def test_mfee3(): """ Unit test for the fee calculation in the mfee3_only_imbalance_fees scenario """ amount = 500_000_000_000_000_000 deposit = TokenAmount(1_000_000_000_000_000_000) imbalance_penalty = calculate_imbalance_fees(deposit, ProportionalFeeAmount(10_000)) fee_schedule = FeeScheduleState(imbalance_penalty=imbalance_penalty, cap_fees=False) channels = make_channel_pair(fee_schedule, deposit) # How much do we need to send so that the target receives `amount`? PFS-like calculation. fee_calculation = get_initial_amount_for_amount_after_fees( amount_after_fees=PaymentAmount(amount), channels=[channels] ) assert fee_calculation amount_with_margin = calculate_safe_amount_with_fee( fee_calculation.amount_without_fees, FeeAmount(sum(fee_calculation.mediation_fees)) ) assert amount_with_margin == 480_850_038_799_922_400 # print values for scenario print("{:_} {:_}".format(deposit - amount_with_margin, amount_with_margin)) for med_fee in running_sum(fee_calculation.mediation_fees): print( "{:_} {:_}".format( deposit - amount_with_margin + med_fee, amount_with_margin - med_fee ) )
def is_valid(self) -> bool: """ Check capacity and settle timeout Capacity: The capacity for the last channel must be at least the payment value. The previous channel's capacity has to be larger than value + last channel's capacity, etc. Settle timeout: The raiden client will not forward payments if the channel over which they receive has a too low settle_timeout. So we should not use such routes. See https://github.com/raiden-network/raiden-services/issues/5. """ log.debug("Checking path validity", nodes=self.nodes, value=self.value) if hasattr(self, "_is_valid"): return self._is_valid required_capacity = self.value edges = reversed(list(self.edge_attrs)) fees = self.fees + [ FeeAmount(0) ] # The hop to the target does not incur mediation fees for edge, fee in zip(edges, fees): # check capacity if edge["view"].capacity < required_capacity: log.debug( "Path invalid because of missing capacity", edge=edge, fee=fees, available_capacity=edge["view"].capacity, required_capacity=required_capacity, ) return False required_capacity = PaymentAmount(required_capacity + fee) # check if settle_timeout / reveal_timeout >= default ratio ratio = edge["view"].settle_timeout / edge["view"].reveal_timeout if ratio < DEFAULT_SETTLE_TO_REVEAL_TIMEOUT_RATIO: log.debug( "Path invalid because of too low reveal timeout ratio", edge=edge, fee=fees, settle_timeout=edge["view"].settle_timeout, reveal_timeout=edge["view"].reveal_timeout, ratio=ratio, required_ratio=DEFAULT_SETTLE_TO_REVEAL_TIMEOUT_RATIO, ) return False # check node reachabilities for node in self.nodes: node_reachability = self.address_to_reachability.get( node, AddressReachability.UNKNOWN) if node_reachability != AddressReachability.REACHABLE: log.debug( "Path invalid because of unavailable node", node=node, node_reachability=node_reachability, ) return False return True
def handle_unlock( target_state: TargetTransferState, state_change: ReceiveUnlock, channel_state: NettingChannelState, ) -> TransitionResult[Optional[TargetTransferState]]: """ Handles a ReceiveUnlock state change. """ balance_proof_sender = state_change.balance_proof.sender is_valid, events, _ = channel.handle_unlock(channel_state, state_change) next_target_state: Optional[TargetTransferState] = target_state if is_valid: transfer = target_state.transfer payment_received_success = EventPaymentReceivedSuccess( token_network_registry_address=channel_state.token_network_registry_address, token_network_address=channel_state.token_network_address, identifier=transfer.payment_identifier, amount=PaymentAmount(transfer.lock.amount), initiator=transfer.initiator, ) unlock_success = EventUnlockClaimSuccess( transfer.payment_identifier, transfer.lock.secrethash ) send_processed = SendProcessed( recipient=balance_proof_sender, message_identifier=state_change.message_identifier, canonical_identifier=CANONICAL_IDENTIFIER_UNORDERED_QUEUE, ) events.extend([payment_received_success, unlock_success, send_processed]) next_target_state = None return TransitionResult(next_target_state, events)
def test_automatic_secret_registration( raiden_chain: List[App], token_addresses: List[TokenAddress] ) -> None: app0, app1 = 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 hold_event_handler = app1.raiden.raiden_event_handler message_handler = app1.raiden.message_handler msg = "hold event handler necessary to control messages" assert isinstance(hold_event_handler, HoldRaidenEventHandler), msg assert isinstance(message_handler, WaitForMessage), msg amount = PaymentAmount(100) identifier = factories.make_payment_id() target = TargetAddress(app1.raiden.address) (secret, secrethash) = factories.make_secret_with_hash() hold_event_handler.hold_secretrequest_for(secrethash=secrethash) locked_transfer_received = message_handler.wait_for_message(LockedTransfer, {}) app0.raiden.start_mediated_transfer_with_secret( token_network_address=token_network_address, amount=amount, target=target, identifier=identifier, secret=secret, ) # Wait for app1 to receive the locked transfer. locked_transfer_received.wait() # Stop app0 to avoid sending the unlock, this must be done after the locked # transfer is sent. app0.raiden.transport.stop() reveal_secret = RevealSecret( message_identifier=MessageID(random.randint(0, UINT64_MAX)), secret=secret, signature=EMPTY_SIGNATURE, ) app0.raiden.sign(reveal_secret) message_handler.on_messages(app1.raiden, [reveal_secret]) chain_state = views.state_from_app(app1) secrethash = sha256_secrethash(secret) target_task = chain_state.payment_mapping.secrethashes_to_task[secrethash] lock_expiration = target_task.target_state.transfer.lock.expiration # type: ignore app1.raiden.proxy_manager.client.wait_until_block(target_block_number=lock_expiration) assert app1.raiden.default_secret_registry.is_secret_registered( secrethash=secrethash, block_identifier=BLOCK_ID_LATEST )
def test_event_filter_for_payments(): secret = factories.make_secret() identifier = PaymentID(1) target = TargetAddress(factories.make_address()) event1 = EventPaymentSentSuccess( token_network_registry_address=UNIT_TOKEN_NETWORK_REGISTRY_ADDRESS, token_network_address=UNIT_TOKEN_NETWORK_ADDRESS, identifier=identifier, amount=PaymentAmount(5), target=target, secret=secret, route=[], ) assert event_filter_for_payments(event=event1, partner_address=None) assert event_filter_for_payments(event=event1, partner_address=Address(target)) assert not event_filter_for_payments( event=event1, partner_address=factories.make_address()) initiator = InitiatorAddress(factories.make_address()) event2 = EventPaymentReceivedSuccess( token_network_registry_address=UNIT_TOKEN_NETWORK_REGISTRY_ADDRESS, token_network_address=UNIT_TOKEN_NETWORK_ADDRESS, identifier=identifier, amount=PaymentAmount(5), initiator=initiator, ) assert event_filter_for_payments(event=event2, partner_address=None) assert event_filter_for_payments(event=event2, partner_address=Address(initiator)) assert not event_filter_for_payments( event=event2, partner_address=factories.make_address()) event3 = EventPaymentSentFailed( token_network_registry_address=UNIT_TOKEN_NETWORK_REGISTRY_ADDRESS, token_network_address=UNIT_TOKEN_NETWORK_ADDRESS, identifier=identifier, target=target, reason="whatever", ) assert event_filter_for_payments(event=event3, partner_address=None) assert event_filter_for_payments(event=event3, partner_address=Address(target)) assert not event_filter_for_payments( event=event3, partner_address=factories.make_address())
def get_amount_for_sending_before_and_after_fees( amount_to_leave_initiator: PaymentAmount, channels: List[NettingChannelState] ) -> Optional[PaymentAmountCalculation]: """ Calculates the amount needed to be sent by the initiator (before fees) in order for his balance to be reduced by `amount_to_leave_initiator`. Also returns the fees kept by the mediators. """ amount_at_target = amount_to_leave_initiator while amount_at_target != 0: calculation = get_initial_payment_for_final_target_amount( final_amount=amount_at_target, channels=channels ) if calculation is None: amount_at_target = PaymentAmount(amount_at_target - 1) continue total_amount_with_mediator_fees = calculation.total_amount mediation_fees = sum(calculation.mediation_fees) estimated_fee = max( mediation_fees, round(INTERNAL_ROUTING_DEFAULT_FEE_PERC * amount_at_target) ) estimated_total_amount_at_initiator = calculate_safe_amount_with_fee( payment_amount=amount_at_target, estimated_fee=FeeAmount(estimated_fee) ) send_amount = min( estimated_total_amount_at_initiator, total_amount_with_mediator_fees - mediation_fees ) send_amount_with_fees = max( estimated_total_amount_at_initiator, total_amount_with_mediator_fees ) if send_amount_with_fees <= amount_to_leave_initiator: return PaymentAmountCalculation( amount_to_send=PaymentAmount(send_amount), mediation_fees=calculation.mediation_fees, amount_with_fees=send_amount_with_fees, ) amount_at_target = PaymentAmount(amount_at_target - 1) return None
def from_dict(cls, data: Dict[str, Any]) -> "ReceiveSecretRequest": instance = cls( payment_identifier=PaymentID(int(data["payment_identifier"])), amount=PaymentAmount(int(data["amount"])), expiration=BlockExpiration(int(data["expiration"])), secrethash=SecretHash(deserialize_bytes(data["secrethash"])), sender=to_canonical_address(data["sender"]), ) instance.revealsecret = data["revealsecret"] return instance
def from_dict(cls, data: Dict[str, Any]) -> 'ReceiveSecretRequest': instance = cls( payment_identifier=PaymentID(int(data['payment_identifier'])), amount=PaymentAmount(int(data['amount'])), expiration=BlockExpiration(int(data['expiration'])), secrethash=SecretHash(deserialize_bytes(data['secrethash'])), sender=to_canonical_address(data['sender']), ) instance.revealsecret = data['revealsecret'] return instance
def test_routing_in_direct_channel(happy_path_fixture, our_address, one_to_n_address): addresses, chain_state, channel_states, _, token_network_state = happy_path_fixture address1, _, _, _ = addresses channel_state1, _ = channel_states # with the transfer of 50 the direct channel should be returned, # so there must be not a pfs call with patch("raiden.routing.get_best_routes_pfs") as pfs_request: pfs_request.return_value = True, [], "feedback_token" routes, _ = get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address1, amount=PaymentAmount(50), previous_address=None, config=CONFIG, privkey=PRIVKEY, ) assert routes[0].next_hop_address == address1 assert routes[0].forward_channel_id == channel_state1.identifier assert not pfs_request.called # with the transfer of 51 the direct channel should not be returned, # so there must be a pfs call with patch("raiden.routing.get_best_routes_pfs") as pfs_request: pfs_request.return_value = True, [], "feedback_token" get_best_routes( chain_state=chain_state, token_network_address=token_network_state.address, one_to_n_address=one_to_n_address, from_address=our_address, to_address=address1, amount=PaymentAmount(51), previous_address=None, config=CONFIG, privkey=PRIVKEY, ) assert pfs_request.called
def make_message(sign: bool = True) -> Message: message = SecretRequest( message_identifier=make_message_identifier(), payment_identifier=PaymentID(1), secrethash=factories.UNIT_SECRETHASH, amount=PaymentAmount(1), expiration=BlockExpiration(10), signature=EMPTY_SIGNATURE, ) if sign: message.sign(LocalSigner(factories.HOP1_KEY)) return message
def test_fee_round_trip(flat_fee, prop_fee, imbalance_fee, amount): """ Tests mediation fee deduction. """ balance = TokenAmount(100_000) prop_fee_per_channel = ppm_fee_per_channel(ProportionalFeeAmount(prop_fee)) imbalance_fee = calculate_imbalance_fees( channel_capacity=balance, proportional_imbalance_fee=ProportionalFeeAmount(imbalance_fee)) payer_channel = factories.create( NettingChannelStateProperties( our_state=NettingChannelEndStateProperties(balance=TokenAmount(0)), partner_state=NettingChannelEndStateProperties(balance=balance), fee_schedule=FeeScheduleState( flat=FeeAmount(flat_fee), proportional=prop_fee_per_channel, imbalance_penalty=imbalance_fee, ), )) payer_channel_backwards = factories.create( NettingChannelStateProperties( partner_state=NettingChannelEndStateProperties( balance=TokenAmount(0)), our_state=NettingChannelEndStateProperties(balance=balance), fee_schedule=FeeScheduleState( flat=FeeAmount(flat_fee), proportional=prop_fee_per_channel, imbalance_penalty=imbalance_fee, ), )) payee_channel = factories.create( NettingChannelStateProperties( our_state=NettingChannelEndStateProperties(balance=balance), partner_state=NettingChannelEndStateProperties( balance=TokenAmount(0)), fee_schedule=FeeScheduleState( flat=FeeAmount(flat_fee), proportional=prop_fee_per_channel, imbalance_penalty=imbalance_fee, ), )) fee_calculation = get_initial_payment_for_final_target_amount( final_amount=PaymentAmount(amount), channels=[payer_channel_backwards, payee_channel]) assert fee_calculation amount_after_fees = get_lock_amount_after_fees( lock=make_hash_time_lock_state(amount=fee_calculation.total_amount), payer_channel=payer_channel, payee_channel=payee_channel, ) assert amount_after_fees assert abs(amount - amount_after_fees) < 100
def test_handle_insufficient_eth(raiden_network, token_addresses, caplog): app0, app1 = raiden_network token = token_addresses[0] registry_address = app0.raiden.default_registry.address channel_state = views.get_channelstate_for( chain_state=views.state_from_raiden(app0.raiden), token_network_registry_address=registry_address, token_address=token, partner_address=app1.raiden.address, ) assert isinstance(channel_state, NettingChannelState) channel_identifier = channel_state.identifier transfer( initiator_app=app0, target_app=app1, amount=PaymentAmount(1), token_address=token, identifier=PaymentID(1), timeout=60, ) app1.raiden.stop() burn_eth(app1.raiden.rpc_client) app1.raiden.start() settle_block_timeout = BlockTimeout( exception_to_throw=RuntimeError("Settle did not happen."), raiden=app0.raiden, block_number=app0.raiden.get_block_number() + channel_state.settle_timeout * 2, retry_timeout=DEFAULT_RETRY_TIMEOUT, ) with settle_block_timeout: RaidenAPI(app0.raiden).channel_close( registry_address=registry_address, token_address=token, partner_address=app1.raiden.address, ) waiting.wait_for_settle( raiden=app0.raiden, token_network_registry_address=registry_address, token_address=token, channel_ids=[channel_identifier], retry_timeout=DEFAULT_RETRY_TIMEOUT, ) assert any( "subtask died" in message and "insufficient ETH" in message for message in caplog.messages )
def test_same_addresses_for_payment(raiden_network, token_addresses): app0, _ = raiden_network api0 = RaidenAPI(app0.raiden) registry_address = app0.raiden.default_registry.address token_address = token_addresses[0] with pytest.raises(SamePeerAddress): api0.transfer( registry_address=registry_address, token_address=token_address, target=app0.raiden.address, amount=PaymentAmount(1), )
def from_dict(cls, data: Dict[str, Any]) -> 'TransferDescriptionWithSecretState': restored = cls( payment_network_identifier=to_canonical_address(data['payment_network_identifier']), payment_identifier=PaymentID(int(data['payment_identifier'])), amount=PaymentAmount(int(data['amount'])), allocated_fee=FeeAmount(int(data['allocated_fee'])), token_network_identifier=to_canonical_address(data['token_network_identifier']), initiator=to_canonical_address(data['initiator']), target=to_canonical_address(data['target']), secret=deserialize_secret(data['secret']), ) return restored
def from_dict(cls, data: Dict[str, Any]) -> "TransferDescriptionWithSecretState": restored = cls( payment_network_identifier=to_canonical_address(data["payment_network_identifier"]), payment_identifier=PaymentID(int(data["payment_identifier"])), amount=PaymentAmount(int(data["amount"])), allocated_fee=FeeAmount(int(data["allocated_fee"])), token_network_identifier=to_canonical_address(data["token_network_identifier"]), initiator=to_canonical_address(data["initiator"]), target=to_canonical_address(data["target"]), secret=deserialize_secret(data["secret"]), ) return restored
def test_routing_simple( token_network_model: TokenNetwork, reachability_state: SimpleReachabilityContainer, addresses: List[Address], ): hex_addrs = [to_checksum_address(addr) for addr in addresses] view01: ChannelView = token_network_model.G[addresses[0]][ addresses[1]]["view"] view10: ChannelView = token_network_model.G[addresses[1]][ addresses[0]]["view"] assert view01.fee_schedule_sender.flat == 0 assert view01.capacity == 90 assert view10.capacity == 60 # 0->2->3 is the shortest path, but has no capacity, so 0->1->4->3 is used paths = token_network_model.get_paths( source=addresses[0], target=addresses[3], value=PaymentAmount(10), max_paths=1, reachability_state=reachability_state, ) assert len(paths) == 1 assert paths[0].to_dict()["path"] == [ hex_addrs[0], hex_addrs[1], hex_addrs[4], hex_addrs[3] ] assert paths[0].to_dict()["estimated_fee"] == 0 # Not connected. no_paths = token_network_model.get_paths( source=addresses[0], target=addresses[5], value=PaymentAmount(10), max_paths=1, reachability_state=reachability_state, ) assert [] == no_paths
def test_same_addresses_for_payment(raiden_network: List[RaidenService], token_addresses): app0, _ = raiden_network api0 = RaidenAPI(app0) registry_address = app0.default_registry.address token_address = token_addresses[0] with pytest.raises(SamePeerAddress): api0.transfer_and_wait( registry_address=registry_address, token_address=token_address, target=TargetAddress(app0.address), amount=PaymentAmount(1), )
def test_regression_payment_complete_after_refund_to_the_initiator( raiden_network: List[RaidenService], token_addresses, settle_timeout, deposit): """Regression test for issue #3915""" app0, app1, app2, app3, app4 = raiden_network token = token_addresses[0] registry_address = app0.default_registry.address # Topology: # # 0 -> 1 -> 2 # | ^ # v | # 3 ------> 4 app_channels = [(app0, app1), (app1, app2), (app0, app3), (app3, app4), (app4, app2)] open_and_wait_for_channels(app_channels, registry_address, token, deposit, settle_timeout) # Use all deposit from app1->app2 to force a refund transfer( initiator_app=app1, target_app=app2, token_address=token, amount=deposit, identifier=PaymentID(1), routes=[[app1.address, app2.address]], ) # Send a transfer that will result in a refund app1->app0 transfer( initiator_app=app0, target_app=app2, token_address=token, amount=PaymentAmount(50), identifier=PaymentID(2), timeout=20, expect_unlock_failures=True, routes=[ [app0.address, app1.address, app2.address], [app0.address, app3.address, app4.address, app2.address], ], ) assert raiden_state_changes_search_for_item( raiden=app0, item_type=ReceiveTransferCancelRoute, attributes={}) assert raiden_events_search_for_item(raiden=app0, item_type=EventRouteFailed, attributes={})
def test_routing_simple( token_network_model: TokenNetwork, address_to_reachability: Dict[Address, AddressReachability], addresses: List[Address], ): hex_addrs = [to_checksum_address(addr) for addr in addresses] view01: ChannelView = token_network_model.G[addresses[0]][addresses[1]]["view"] view10: ChannelView = token_network_model.G[addresses[1]][addresses[0]]["view"] assert view01.deposit == 100 assert view01.fee_schedule_sender.flat == 0 assert view01.capacity == 90 assert view10.capacity == 60 # 0->2->3 is the shortest path, but has no capacity, so 0->1->4->3 is used paths = token_network_model.get_paths( source=addresses[0], target=addresses[3], value=PaymentAmount(10), max_paths=1, address_to_reachability=address_to_reachability, ) assert len(paths) == 1 assert paths[0] == { "path": [hex_addrs[0], hex_addrs[1], hex_addrs[4], hex_addrs[3]], "estimated_fee": 0, } # Not connected. with pytest.raises(NetworkXNoPath): token_network_model.get_paths( source=addresses[0], target=addresses[5], value=PaymentAmount(10), max_paths=1, address_to_reachability=address_to_reachability, )
def test_transfer_with_invalid_address_type(raiden_network, token_addresses): app0, _ = raiden_network token_address = token_addresses[0] target_address = "\xf0\xef3\x01\xcd\xcfe\x0f4\x9c\xf6d\xa2\x01?X4\x84\xa9\xf1" # Enforce sandwich encoding. Calling `transfer` with a non binary address # raises an exception with pytest.raises(InvalidBinaryAddress): RaidenAPI(app0.raiden).transfer( app0.raiden.default_registry.address, token_address, PaymentAmount(10), target=target_address, # type: ignore transfer_timeout=10, )
def test_routing_result_order( token_network_model: TokenNetwork, address_to_reachability: Dict[Address, AddressReachability], addresses: List[Address], ): hex_addrs = [to_checksum_address(addr) for addr in addresses] paths = token_network_model.get_paths( addresses[0], addresses[2], value=PaymentAmount(10), max_paths=5, address_to_reachability=address_to_reachability, ) # 5 paths requested, but only 1 is available assert len(paths) == 1 assert paths[0] == {"path": [hex_addrs[0], hex_addrs[1], hex_addrs[2]], "estimated_fee": 0}