def test_mediator_task_view(): """Same as above for mediator tasks.""" secret1 = factories.make_secret(1) locked_amount1 = TokenAmount(11) payee_transfer = factories.create( factories.LockedTransferUnsignedStateProperties(secret=secret1)) payer_transfer = factories.create( factories.LockedTransferSignedStateProperties( secret=secret1, payment_identifier=PaymentID(1), locked_amount=locked_amount1)) secrethash1 = payee_transfer.lock.secrethash route_state = RouteState(route=[payee_transfer.target]) transfer_state1 = MediatorTransferState(secrethash=secrethash1, routes=[route_state]) # pylint: disable=E1101 transfer_state1.transfers_pair.append( MediationPairState( payer_transfer=payer_transfer, payee_transfer=payee_transfer, payee_address=payee_transfer.target, )) task1 = MediatorTask( token_network_address=factories.UNIT_TOKEN_NETWORK_ADDRESS, mediator_state=transfer_state1) secret2 = factories.make_secret(2) locked_amount2 = TokenAmount(13) transfer2 = factories.create( factories.LockedTransferSignedStateProperties( secret=secret2, payment_identifier=PaymentID(2), locked_amount=locked_amount2)) secrethash2 = transfer2.lock.secrethash transfer_state2 = MediatorTransferState(secrethash=secrethash2, routes=[route_state]) transfer_state2.waiting_transfer = WaitingTransferState(transfer=transfer2) task2 = MediatorTask( token_network_address=factories.UNIT_TOKEN_NETWORK_ADDRESS, mediator_state=transfer_state2) payment_mapping = { secrethash1: cast(TransferTask, task1), secrethash2: cast(TransferTask, task2), } view = transfer_tasks_view(payment_mapping) assert len(view) == 2 if view[0].get("payment_identifier") == "1": pending_transfer, waiting_transfer = view else: waiting_transfer, pending_transfer = view assert pending_transfer.get("role") == waiting_transfer.get( "role") == "mediator" assert pending_transfer.get("payment_identifier") == "1" assert waiting_transfer.get("payment_identifier") == "2" assert pending_transfer.get("locked_amount") == str(locked_amount1) assert waiting_transfer.get("locked_amount") == str(locked_amount2)
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_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 from_dict( cls, data: Dict[str, Any]) -> "EventInvalidReceivedLockedTransfer": restored = cls(payment_identifier=PaymentID( int(data["payment_identifier"])), reason=data["reason"]) return restored
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 from_dict(cls, data: Dict[str, Any]) -> "EventUnlockClaimSuccess": restored = cls( identifier=PaymentID(int(data["identifier"])), secrethash=deserialize_secret_hash(data["secrethash"]), ) return restored
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_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_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 from_dict(cls, data: Dict[str, Any]) -> 'EventUnlockSuccess': restored = cls( identifier=PaymentID(int(data['identifier'])), secrethash=deserialize_secret_hash(data['secrethash']), ) return restored
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 from_dict(cls, data: Dict[str, Any]) -> "EventUnlockFailed": restored = cls( identifier=PaymentID(int(data["identifier"])), secrethash=deserialize_secret_hash(data["secrethash"]), reason=data["reason"], ) return restored
def from_dict(cls, data: Dict[str, Any]) -> 'EventUnlockClaimFailed': restored = cls( identifier=PaymentID(int(data['identifier'])), secrethash=deserialize_secret_hash(data['secrethash']), reason=data['reason'], ) return restored
def test_locked_transfer_secret_registered_onchain( raiden_network, token_addresses, secret_registry_address, retry_timeout ): app0 = raiden_network[0] 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 ) amount = TokenAmount(1) target = factories.UNIT_TRANSFER_INITIATOR identifier = PaymentID(1) transfer_secret = make_secret() secret_registry_proxy = app0.raiden.proxy_manager.secret_registry( secret_registry_address, block_identifier=chain_state.block_hash ) secret_registry_proxy.register_secret(secret=transfer_secret) # Wait until our node has processed the block that the secret registration was mined at block_number = app0.raiden.get_block_number() wait_for_block( raiden=app0.raiden, block_number=block_number + DEFAULT_NUMBER_OF_BLOCK_CONFIRMATIONS, retry_timeout=retry_timeout, ) # Test that sending a transfer with a secret already registered on-chain fails with pytest.raises(RaidenUnrecoverableError): app0.raiden.start_mediated_transfer_with_secret( token_network_address=token_network_address, amount=amount, target=target, identifier=identifier, secret=transfer_secret, ) # Test that receiving a transfer with a secret already registered on chain fails expiration = BlockExpiration(9999) locked_transfer = factories.create( factories.LockedTransferProperties( amount=amount, target=app0.raiden.address, expiration=expiration, secret=transfer_secret, ) ) message_handler = MessageHandler() message_handler.handle_message_lockedtransfer(app0.raiden, locked_transfer) state_changes = app0.raiden.wal.storage.get_statechanges_by_range(RANGE_ALL_STATE_CHANGES) transfer_statechange_dispatched = search_for_item( state_changes, ActionInitMediator, {} ) or search_for_item(state_changes, ActionInitTarget, {}) assert not transfer_statechange_dispatched
def __init__(self, chain_state: ChainState, channel_state: NettingChannelState): self.secret = random_secret() self.secrethash = SecretHash(sha3(self.secret)) self.lock_expiration = get_initial_lock_expiration( chain_state.block_number, channel_state.reveal_timeout) self.payment_identifier = PaymentID(create_default_identifier()) self.message_identifier = MessageID( message_identifier_from_prng(chain_state.pseudo_random_generator))
def from_dict(cls, data: Dict[str, Any]) -> 'EventPaymentSentFailed': restored = cls( payment_network_identifier=to_canonical_address(data['payment_network_identifier']), token_network_identifier=to_canonical_address(data['token_network_identifier']), identifier=PaymentID(int(data['identifier'])), target=to_canonical_address(data['target']), reason=data['reason'], ) return restored
def from_dict(cls, data: Dict[str, Any]) -> 'EventPaymentReceivedSuccess': restored = cls( payment_network_identifier=to_canonical_address(data['payment_network_identifier']), token_network_identifier=to_canonical_address(data['token_network_identifier']), identifier=PaymentID(int(data['identifier'])), amount=TokenAmount(int(data['amount'])), initiator=to_canonical_address(data['initiator']), ) return restored
def from_dict( cls, data: Dict[str, Any], ) -> 'EventInvalidReceivedLockedTransfer': restored = cls( payment_identifier=PaymentID(int(data['payment_identifier'])), reason=data['reason'], ) return restored
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 from_dict(cls, data: Dict[str, Any]) -> "LockedTransferUnsignedState": restored = cls( payment_identifier=PaymentID(int(data["payment_identifier"])), token=to_canonical_address(data["token"]), balance_proof=data["balance_proof"], lock=data["lock"], initiator=to_canonical_address(data["initiator"]), target=to_canonical_address(data["target"]), ) return restored
def from_dict(cls, data: Dict[str, Any]) -> 'LockedTransferUnsignedState': restored = cls( payment_identifier=PaymentID(int(data['payment_identifier'])), token=to_canonical_address(data['token']), balance_proof=data['balance_proof'], lock=data['lock'], initiator=to_canonical_address(data['initiator']), target=to_canonical_address(data['target']), ) return restored
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 from_dict(cls, data: Dict[str, Any]) -> 'SendSecretRequest': restored = cls( recipient=to_canonical_address(data['recipient']), channel_identifier=ChannelID(int(data['channel_identifier'])), message_identifier=MessageID(int(data['message_identifier'])), payment_identifier=PaymentID(int(data['payment_identifier'])), amount=TokenAmount(int(data['amount'])), expiration=BlockExpiration(int(data['expiration'])), secrethash=SecretHash(serialization.deserialize_bytes(data['secrethash'])), ) return restored
def from_dict(cls, data: Dict[str, Any]) -> 'SendBalanceProof': restored = cls( recipient=to_canonical_address(data['recipient']), channel_identifier=ChannelID(int(data['channel_identifier'])), message_identifier=MessageID(int(data['message_identifier'])), payment_identifier=PaymentID(int(data['payment_identifier'])), token_address=to_canonical_address(data['token_address']), secret=Secret(serialization.deserialize_bytes(data['secret'])), balance_proof=data['balance_proof'], ) return restored
def from_dict(cls, data: Dict[str, Any]) -> "EventPaymentSentFailed": restored = cls( payment_network_identifier=to_canonical_address( data["payment_network_identifier"]), token_network_identifier=to_canonical_address( data["token_network_identifier"]), identifier=PaymentID(int(data["identifier"])), target=to_canonical_address(data["target"]), reason=data["reason"], ) return restored
def from_dict(cls, data: Dict[str, Any]) -> "SendSecretRequest": restored = cls( recipient=to_canonical_address(data["recipient"]), channel_identifier=ChannelID(int(data["channel_identifier"])), message_identifier=MessageID(int(data["message_identifier"])), payment_identifier=PaymentID(int(data["payment_identifier"])), amount=PaymentWithFeeAmount(int(data["amount"])), expiration=BlockExpiration(int(data["expiration"])), secrethash=deserialize_secret_hash(data["secrethash"]), ) return restored
def from_dict(cls, data: Dict[str, Any]) -> "SendBalanceProof": restored = cls( recipient=to_canonical_address(data["recipient"]), channel_identifier=ChannelID(int(data["channel_identifier"])), message_identifier=MessageID(int(data["message_identifier"])), payment_identifier=PaymentID(int(data["payment_identifier"])), token_address=to_canonical_address(data["token_address"]), secret=deserialize_secret(data["secret"]), balance_proof=data["balance_proof"], ) return restored
def from_dict(cls, data: Dict[str, Any]) -> "EventPaymentReceivedSuccess": restored = cls( payment_network_identifier=to_canonical_address( data["payment_network_identifier"]), token_network_identifier=to_canonical_address( data["token_network_identifier"]), identifier=PaymentID(int(data["identifier"])), amount=TokenAmount(int(data["amount"])), initiator=to_canonical_address(data["initiator"]), ) return restored
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 )