def initiator_init( raiden: 'RaidenService', transfer_identifier: PaymentID, transfer_amount: PaymentAmount, transfer_secret: Secret, token_network_identifier: TokenNetworkID, target_address: TargetAddress, ): msg = 'Should never end up initiating transfer with Secret 0x0' assert transfer_secret != constants.EMPTY_HASH, msg transfer_state = TransferDescriptionWithSecretState( raiden.default_registry.address, transfer_identifier, transfer_amount, token_network_identifier, InitiatorAddress(raiden.address), target_address, transfer_secret, ) previous_address = None routes = routing.get_best_routes( chain_state=views.state_from_raiden(raiden), token_network_id=token_network_identifier, from_address=InitiatorAddress(raiden.address), to_address=target_address, amount=transfer_amount, previous_address=previous_address, config=raiden.config, ) init_initiator_statechange = ActionInitInitiator( transfer_state, routes, ) return init_initiator_statechange
def handle_message_refundtransfer(raiden: RaidenService, message: RefundTransfer): token_network_address = message.token_network_address from_transfer = lockedtransfersigned_from_message(message) chain_state = views.state_from_raiden(raiden) routes = get_best_routes( chain_state=chain_state, token_network_id=TokenNetworkID(token_network_address), from_address=InitiatorAddress(raiden.address), to_address=from_transfer.target, amount=from_transfer.lock.amount, previous_address=message.sender, config=raiden.config, ) role = views.get_transfer_role( chain_state, from_transfer.lock.secrethash, ) if role == 'initiator': secret = random_secret() state_change = ReceiveTransferRefundCancelRoute( routes=routes, transfer=from_transfer, secret=secret, ) else: state_change = ReceiveTransferRefund( transfer=from_transfer, routes=routes, ) raiden.handle_state_change(state_change)
def event_filter_for_payments( event: Event, chain_state: Optional[ChainState] = None, partner_address: Optional[Address] = None, token_address: Optional[TokenAddress] = None, ) -> bool: """Filters payment history related events depending on given arguments - If no other args are given, all payment related events match. - If a token network identifier is given then only payment events for that match. - If a partner is also given then if the event is a payment sent event and the target matches it's returned. If it's a payment received and the initiator matches. then it's returned. - If a token address is given then all events are filtered to be about that token. """ sent_and_target_matches = isinstance( event, (EventPaymentSentFailed, EventPaymentSentSuccess) ) and (partner_address is None or event.target == TargetAddress(partner_address)) received_and_initiator_matches = isinstance(event, EventPaymentReceivedSuccess) and ( partner_address is None or event.initiator == InitiatorAddress(partner_address) ) token_address_matches = True if token_address: assert chain_state, "Filtering for token_address without a chain state is an error" token_network = get_token_network_by_address( chain_state=chain_state, token_network_address=event.token_network_address, # type: ignore ) if not token_network: token_address_matches = False else: token_address_matches = token_address == token_network.token_address return token_address_matches and (sent_and_target_matches or received_and_initiator_matches)
def initiator_init( raiden: 'RaidenService', transfer_identifier: PaymentID, transfer_amount: PaymentAmount, transfer_secret: Secret, transfer_fee: FeeAmount, token_network_identifier: TokenNetworkID, target_address: TargetAddress, ): assert transfer_secret != constants.EMPTY_HASH, f'Empty secret node:{raiden!r}' transfer_state = TransferDescriptionWithSecretState( payment_network_identifier=raiden.default_registry.address, payment_identifier=transfer_identifier, amount=transfer_amount, allocated_fee=transfer_fee, token_network_identifier=token_network_identifier, initiator=InitiatorAddress(raiden.address), target=target_address, secret=transfer_secret, ) previous_address = None routes = routing.get_best_routes( chain_state=views.state_from_raiden(raiden), token_network_id=token_network_identifier, from_address=InitiatorAddress(raiden.address), to_address=target_address, amount=transfer_amount, previous_address=previous_address, config=raiden.config, privkey=raiden.privkey, ) init_initiator_statechange = ActionInitInitiator( transfer_state, routes, ) return init_initiator_statechange
def test_received_lockedtransfer_closedchannel( raiden_network: List[RaidenService], reveal_timeout, token_addresses, deposit ): app0, app1 = raiden_network registry_address = app0.default_registry.address token_address = token_addresses[0] token_network_address = views.get_token_network_address_by_token_address( views.state_from_raiden(app0), app0.default_registry.address, token_address ) assert token_network_address channel0 = get_channelstate(app0, app1, token_network_address) RaidenAPI(app1).channel_close(registry_address, token_address, app0.address) app0.rpc_client.wait_until_block( target_block_number=BlockNumber(app0.rpc_client.block_number() + 1) ) # Now receive one mediated transfer for the closed channel lock_amount = LockedAmount(10) payment_identifier = PaymentID(1) expiration = reveal_timeout * 2 mediated_transfer_message = LockedTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=make_message_identifier(), payment_identifier=payment_identifier, nonce=Nonce(1), token_network_address=token_network_address, token=token_address, channel_identifier=channel0.identifier, transferred_amount=TokenAmount(0), locked_amount=lock_amount, recipient=app1.address, locksroot=make_locksroot(), lock=Lock( amount=PaymentWithFeeAmount(lock_amount), expiration=expiration, secrethash=UNIT_SECRETHASH, ), target=TargetAddress(app1.address), initiator=InitiatorAddress(app0.address), signature=EMPTY_SIGNATURE, metadata=Metadata(routes=[RouteMetadata(route=[app1.address])]), ) sign_and_inject(mediated_transfer_message, app0.signer, app1) # The local state must not change since the channel is already closed assert_synced_channel_state(token_network_address, app0, deposit, [], app1, deposit, [])
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=TokenAmount(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 test_receive_lockedtransfer_invalidrecipient( raiden_network: List[RaidenService], token_addresses, reveal_timeout, deposit ): app0, app1 = raiden_network token_address = token_addresses[0] token_network_address = views.get_token_network_address_by_token_address( views.state_from_raiden(app0), app0.default_registry.address, token_address ) assert token_network_address channel0 = get_channelstate(app0, app1, token_network_address) payment_identifier = PaymentID(1) invalid_recipient = make_address() lock_amount = LockedAmount(10) expiration = reveal_timeout * 2 mediated_transfer_message = LockedTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=make_message_identifier(), payment_identifier=payment_identifier, nonce=Nonce(1), token_network_address=token_network_address, token=token_address, channel_identifier=channel0.identifier, transferred_amount=TokenAmount(0), locked_amount=lock_amount, recipient=invalid_recipient, locksroot=make_locksroot(), lock=Lock( amount=PaymentWithFeeAmount(lock_amount), expiration=expiration, secrethash=UNIT_SECRETHASH, ), target=TargetAddress(app1.address), initiator=InitiatorAddress(app0.address), signature=EMPTY_SIGNATURE, metadata=Metadata(routes=[RouteMetadata(route=[app1.address])]), ) sign_and_inject(mediated_transfer_message, app0.signer, app1) assert_synced_channel_state(token_network_address, app0, deposit, [], app1, deposit, [])
def handle_message_refundtransfer(raiden: RaidenService, message: RefundTransfer) -> None: token_network_address = message.token_network_address from_transfer = lockedtransfersigned_from_message(message) chain_state = views.state_from_raiden(raiden) # FIXME: Shouldn't request routes here routes, _ = get_best_routes( chain_state=chain_state, token_network_id=TokenNetworkID(token_network_address), one_to_n_address=raiden.default_one_to_n_address, from_address=InitiatorAddress(raiden.address), to_address=from_transfer.target, amount=PaymentAmount( from_transfer.lock.amount), # FIXME: mypy; deprecated by #3863 previous_address=message.sender, config=raiden.config, privkey=raiden.privkey, ) role = views.get_transfer_role( chain_state=chain_state, secrethash=from_transfer.lock.secrethash) state_change: StateChange if role == "initiator": old_secret = views.get_transfer_secret( chain_state, from_transfer.lock.secrethash) # We currently don't allow multi routes if the initiator does not # hold the secret. In such case we remove all other possible routes # which allow the API call to return with with an error message. if old_secret == EMPTY_SECRET: routes = list() secret = random_secret() state_change = ReceiveTransferRefundCancelRoute( routes=routes, transfer=from_transfer, secret=secret) else: state_change = ReceiveTransferRefund(transfer=from_transfer, routes=routes) raiden.handle_and_track_state_change(state_change)
def test_regression_multiple_revealsecret( raiden_network: List[App], token_addresses: List[TokenAddress]) -> None: """ Multiple RevealSecret messages arriving at the same time must be handled properly. Unlock handling followed these steps: The Unlock message arrives The secret is registered The channel is updated and the correspoding lock is removed * A balance proof for the new channel state is created and sent to the payer The channel is unregistered for the given secrethash The step marked with an asterisk above introduced a context-switch. This allowed a second Reveal Unlock message to be handled before the channel was unregistered. And because the channel was already updated an exception was raised for an unknown secret. """ app0, app1 = raiden_network token = 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) assert token_network_address channelstate_0_1 = get_channelstate(app0, app1, token_network_address) payment_identifier = PaymentID(1) secret, secrethash = make_secret_with_hash() expiration = BlockExpiration(app0.raiden.get_block_number() + 100) lock_amount = PaymentWithFeeAmount(10) lock = Lock(amount=lock_amount, expiration=expiration, secrethash=secrethash) nonce = Nonce(1) transferred_amount = TokenAmount(0) mediated_transfer = LockedTransfer( chain_id=UNIT_CHAIN_ID, message_identifier=make_message_identifier(), payment_identifier=payment_identifier, nonce=nonce, token_network_address=token_network_address, token=token, channel_identifier=channelstate_0_1.identifier, transferred_amount=transferred_amount, locked_amount=LockedAmount(lock_amount), recipient=app1.raiden.address, locksroot=Locksroot(lock.lockhash), lock=lock, target=TargetAddress(app1.raiden.address), initiator=InitiatorAddress(app0.raiden.address), signature=EMPTY_SIGNATURE, metadata=Metadata(routes=[ RouteMetadata(route=[app0.raiden.address, app1.raiden.address]) ]), ) app0.raiden.sign(mediated_transfer) app1.raiden.on_messages([mediated_transfer]) reveal_secret = RevealSecret(message_identifier=make_message_identifier(), secret=secret, signature=EMPTY_SIGNATURE) app0.raiden.sign(reveal_secret) token_network_address = channelstate_0_1.token_network_address unlock = Unlock( chain_id=UNIT_CHAIN_ID, message_identifier=make_message_identifier(), payment_identifier=payment_identifier, nonce=Nonce(mediated_transfer.nonce + 1), token_network_address=token_network_address, channel_identifier=channelstate_0_1.identifier, transferred_amount=TokenAmount(lock_amount), locked_amount=LockedAmount(0), locksroot=LOCKSROOT_OF_NO_LOCKS, secret=secret, signature=EMPTY_SIGNATURE, ) app0.raiden.sign(unlock) messages = [unlock, reveal_secret] receive_method = app1.raiden.on_messages wait = set( gevent.spawn_later(0.1, receive_method, [data]) for data in messages) gevent.joinall(wait, raise_error=True)
def test_receive_lockedtransfer_invalidnonce( raiden_network: List[RaidenService], 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_raiden(app0), app0.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, routes=[[app0.address, app1.address, app2.address]], ) 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=LockedAmount(amount), recipient=app1.address, locksroot=make_locksroot(), lock=Lock( amount=PaymentWithFeeAmount(amount), expiration=expiration, secrethash=UNIT_SECRETHASH ), target=TargetAddress(app2.address), initiator=InitiatorAddress(app0.address), signature=EMPTY_SIGNATURE, metadata=Metadata(routes=[RouteMetadata(route=[app1.address, app2.address])]), ) sign_and_inject(mediated_transfer_message, app0.signer, app1) with block_timeout_for_transfer_by_secrethash(app1, secrethash): wait_assert( assert_synced_channel_state, token_network_address, app0, deposit - amount, [], app1, deposit + amount, [], )