def test_locked_transfer_additional_hash_contains_route_metadata_hash(): one_locked_transfer = factories.create( factories.LockedTransferProperties()) route_metadata = factories.create( factories.RouteMetadataProperties( route=[factories.HOP2, factories.HOP1])) another_locked_transfer = factories.create( factories.LockedTransferProperties(metadata=factories.create( factories.MetadataProperties(routes=[route_metadata])))) assert ( one_locked_transfer.message_hash != another_locked_transfer.message_hash ), "LockedTransfers with different routes should have different message hashes"
def test_target_task_view(): """Same as above for target tasks.""" secret = factories.make_secret() transfer = factories.create( factories.LockedTransferSignedStateProperties( transfer=factories.LockedTransferProperties(secret=secret), )) secrethash = transfer.lock.secrethash mediator = factories.make_address() mediator_channel = factories.create( factories.NettingChannelStateProperties( partner_state=factories.NettingChannelEndStateProperties( address=mediator, balance=100), )) transfer_state = TargetTransferState(route=None, transfer=transfer, secret=secret) task = TargetTask( token_network_identifier=factories.UNIT_TOKEN_NETWORK_ADDRESS, channel_identifier=mediator_channel.identifier, target_state=transfer_state, ) payment_mapping = {secrethash: task} view = transfer_tasks_view(payment_mapping) assert len(view) == 1 pending_transfer = view[0] assert pending_transfer.get('role') == 'target' assert pending_transfer.get('locked_amount') == str( transfer.balance_proof.locked_amount) assert pending_transfer.get('payment_identifier') == str( transfer.payment_identifier)
def test_mediated_transfer_calls_pfs(raiden_network, token_addresses): app0, = 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) with patch("raiden.routing.query_paths", return_value=([], None)) as patched: app0.raiden.start_mediated_transfer_with_secret( token_network_address=token_network_address, amount=10, target=factories.HOP1, identifier=1, secret=b"1" * 32, ) assert not patched.called # Setup PFS config app0.raiden.config["pfs_config"] = PFSConfig( info=PFSInfo( url="mock-address", chain_id=app0.raiden.rpc_client.chain_id, token_network_registry_address=token_network_registry_address, payment_address=factories.make_address(), message="", operator="", version="", price=TokenAmount(0), ), maximum_fee=TokenAmount(100), iou_timeout=BlockNumber(100), max_paths=5, ) app0.raiden.start_mediated_transfer_with_secret( token_network_address=token_network_address, amount=11, target=factories.HOP2, identifier=2, secret=b"2" * 32, ) assert patched.call_count == 1 # Mediator should not re-query PFS locked_transfer = factories.create( factories.LockedTransferProperties( amount=TokenAmount(5), initiator=factories.HOP1, target=TargetAddress(factories.HOP2), sender=factories.HOP1, pkey=factories.HOP1_KEY, token=token_address, canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_address), )) app0.raiden.mediate_mediated_transfer(locked_transfer) assert patched.call_count == 1
def make_from_route_from_counter(counter): from_channel = factories.make_channel( partner_balance=next(counter), partner_address=factories.HOP1, token_address=factories.make_address(), channel_identifier=next(counter), ) from_route = factories.route_from_channel(from_channel) expiration = factories.UNIT_REVEAL_TIMEOUT + 1 from_transfer = factories.make_signed_transfer_for( from_channel, factories.LockedTransferSignedStateProperties( transfer=factories.LockedTransferProperties( balance_proof=factories.BalanceProofProperties( transferred_amount=0, token_network_identifier=from_channel. token_network_identifier, ), amount=1, expiration=expiration, secret=sha3(factories.make_secret(next(counter))), initiator=factories.make_address(), target=factories.make_address(), payment_identifier=next(counter), ), sender=factories.HOP1, pkey=factories.HOP1_KEY, ), ) return from_route, from_transfer
def test_target_reject_keccak_empty_hash(): lock_amount = 7 block_number = 1 pseudo_random_generator = random.Random() channels = make_channel_set([channel_properties2]) expiration = block_number + channels[0].settle_timeout - channels[ 0].reveal_timeout from_transfer = factories.make_signed_transfer_for( channels[0], factories.LockedTransferSignedStateProperties( transfer=factories.LockedTransferProperties( amount=lock_amount, target=channels.our_address(0), expiration=expiration, secret=EMPTY_HASH, ), ), allow_invalid=True, ) init = ActionInitTarget(route=channels.get_route(0), transfer=from_transfer) init_transition = target.state_transition( target_state=None, state_change=init, channel_state=channels[0], pseudo_random_generator=pseudo_random_generator, block_number=block_number, ) assert init_transition.new_state is None
def test_channel_closed_must_clear_ordered_messages(chain_state, token_network_state, netting_channel_state): recipient = netting_channel_state.partner_state.address message_identifier = random.randint(0, 2**16) amount = 10 queue_identifier = QueueIdentifier( recipient=recipient, canonical_identifier=netting_channel_state.canonical_identifier) # Regression test: # The code delivered_message handler worked only with a queue of one # element message = factories.create( factories.LockedTransferProperties( message_identifier=message_identifier, token=token_network_state.token_address, canonical_identifier=netting_channel_state.canonical_identifier, transferred_amount=amount, recipient=recipient, )) chain_state.queueids_to_queues[queue_identifier] = [message] closed = state_change.ContractReceiveChannelClosed( transaction_hash=EMPTY_HASH, transaction_from=recipient, canonical_identifier=netting_channel_state.canonical_identifier, block_number=1, block_hash=factories.make_block_hash(), ) iteration = node.handle_state_change(chain_state, closed) assert queue_identifier not in iteration.new_state.queueids_to_queues
def run_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) payment_network_id = app0.raiden.default_registry.address token_network_identifier = views.get_token_network_identifier_by_token_address( chain_state, payment_network_id, token_address) amount = 1 target = factories.UNIT_TRANSFER_INITIATOR identifier = 1 transfer_secret = sha3(target + b"1") secret_registry_proxy = app0.raiden.chain.secret_registry( secret_registry_address) 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_identifier=token_network_identifier, amount=amount, fee=0, target=target, identifier=identifier, payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE, secret=transfer_secret, ) # Test that receiving a transfer with a secret already registered on chain fails expiration = 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_identifier( 0, "latest") transfer_statechange_dispatched = search_for_item( state_changes, ActionInitMediator, {}) or search_for_item( state_changes, ActionInitTarget, {}) assert not transfer_statechange_dispatched
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 test_locked_transfer_with_metadata(): locked_transfer = factories.create(factories.LockedTransferProperties()) assert isinstance(locked_transfer, LockedTransfer) assert isinstance(locked_transfer.metadata, Metadata) # pylint: disable=E1101 assert locked_transfer.metadata.routes[0].route == [ factories.HOP1, factories.HOP2 ]
def test_mediated_transfer_min_max(amount, payment_identifier, nonce, transferred_amount): mediated_transfer = factories.create( factories.LockedTransferProperties( amount=amount, payment_identifier=payment_identifier, nonce=nonce, transferred_amount=transferred_amount, )) mediated_transfer._data_to_sign( ) # Just test that packing works without exceptions.
def test_mediated_transfer_min_max(amount, payment_identifier, fee, nonce, transferred_amount): mediated_transfer = factories.create( factories.LockedTransferProperties( amount=amount, payment_identifier=payment_identifier, nonce=nonce, transferred_amount=transferred_amount, fee=fee, )) assert decode(mediated_transfer.encode()) == mediated_transfer
def run_test_mediated_transfer_calls_pfs(raiden_network, token_addresses): app0, = raiden_network token_address = token_addresses[0] chain_state = views.state_from_app(app0) payment_network_id = app0.raiden.default_registry.address token_network_id = views.get_token_network_identifier_by_token_address( chain_state, payment_network_id, token_address) with patch("raiden.routing.query_paths", return_value=([], None)) as patched: app0.raiden.start_mediated_transfer_with_secret( token_network_identifier=token_network_id, amount=10, fee=0, target=factories.HOP1, identifier=1, payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE, secret=b"1" * 32, ) assert not patched.called config_patch = dict( pathfinding_service_address="mock-address", pathfinding_eth_address=factories.make_checksum_address(), ) with patch.dict(app0.raiden.config["services"], config_patch): app0.raiden.start_mediated_transfer_with_secret( token_network_identifier=token_network_id, amount=11, fee=0, target=factories.HOP2, identifier=2, payment_hash_invoice=EMPTY_PAYMENT_HASH_INVOICE, secret=b"2" * 32, ) assert patched.call_count == 1 locked_transfer = factories.create( factories.LockedTransferProperties( amount=TokenAmount(5), initiator=factories.HOP1, target=factories.HOP2, sender=factories.HOP1, pkey=factories.HOP1_KEY, token=token_address, canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_id), )) app0.raiden.mediate_mediated_transfer(locked_transfer) assert patched.call_count == 2
def test_mediated_transfer_min_max(amount, payment_identifier, nonce, transferred_amount): mediated_transfer = factories.create( factories.LockedTransferProperties( amount=amount, payment_identifier=payment_identifier, nonce=nonce, transferred_amount=transferred_amount, ) ) mediated_transfer.sign(signer) data = JSONSerializer.serialize(mediated_transfer) assert JSONSerializer.deserialize(data) == mediated_transfer
def make_target_transfer(channel, amount=None, expiration=None, initiator=None, block_number=1): default_expiration = block_number + channel.settle_timeout - channel.reveal_timeout return factories.make_signed_transfer_for( channel, factories.LockedTransferSignedStateProperties( transfer=factories.LockedTransferProperties( amount=amount or channel.partner_state.contract_balance, expiration=expiration or default_expiration, initiator=initiator or UNIT_TRANSFER_INITIATOR, target=channel.our_state.address, ), ), )
def test_initiator_task_view(): """Test transfer_tasks_view(), which is used to generate the output of the pending transfers API, with an initiator task. """ channel_id = factories.UNIT_CHANNEL_ID secret = factories.make_secret() transfer = factories.create( factories.LockedTransferProperties(secret=secret)) secrethash = transfer.lock.secrethash transfer_description = TransferDescriptionWithSecretState( payment_network_identifier=factories.UNIT_PAYMENT_NETWORK_IDENTIFIER, payment_identifier=transfer.payment_identifier, amount=transfer.balance_proof.locked_amount, allocated_fee=0, token_network_identifier=factories.UNIT_TOKEN_NETWORK_ADDRESS, initiator=transfer.initiator, target=transfer.target, secret=secret, ) transfer_state = InitiatorTransferState( transfer_description=transfer_description, channel_identifier=channel_id, transfer=transfer, revealsecret=None, ) payment_state = InitiatorPaymentState({secrethash: transfer_state}) task = InitiatorTask( token_network_identifier=factories.UNIT_TOKEN_NETWORK_ADDRESS, manager_state=payment_state, ) payment_mapping = {secrethash: task} view = transfer_tasks_view(payment_mapping) assert len(view) == 1 pending_transfer = view[0] assert pending_transfer.get('role') == 'initiator' balance_proof = transfer.balance_proof assert pending_transfer.get('channel_identifier') == str( balance_proof.channel_identifier) assert pending_transfer.get('locked_amount') == str( balance_proof.locked_amount) assert pending_transfer.get('transferred_amount') == str( balance_proof.transferred_amount)
def test_changing_route_metadata_will_invalidate_lock_transfer_signature(): one_locked_transfer = factories.create( factories.LockedTransferProperties(sender=ADDRESS, pkey=PRIVKEY)) new_route_metadata = factories.create( factories.RouteMetadataProperties( route=[factories.HOP2, factories.HOP1])) new_metadata = factories.create( factories.Metadata(routes=[new_route_metadata])) assert ADDRESS == recover(one_locked_transfer._data_to_sign(), one_locked_transfer.signature ), "signature does not match signer address" one_locked_transfer.metadata = new_metadata assert ADDRESS != recover( one_locked_transfer._data_to_sign(), one_locked_transfer.signature ), "signature should not be valid after data being altered"
def test_mediated_transfer_invalid_values(invalid_values): for invalid_value in invalid_values: with pytest.raises(ValueError): factories.create( factories.LockedTransferProperties(**invalid_value))
def test_message_handler(): """ Test for MessageHandler.on_message and the different methods it dispatches into. Each of them results in a call to a RaidenService method, which is checked with a Mock. """ our_address = factories.make_address() sender_privkey, sender = factories.make_privkey_address() signer = LocalSigner(sender_privkey) message_handler = MessageHandler() mock_raiden = Mock( address=our_address, default_secret_registry=Mock(is_secret_registered=lambda **_: False) ) properties = factories.LockedTransferProperties(sender=sender, pkey=sender_privkey) locked_transfer = factories.create(properties) message_handler.on_message(mock_raiden, locked_transfer) assert_method_call(mock_raiden, "mediate_mediated_transfer", locked_transfer) locked_transfer_for_us = factories.create(factories.replace(properties, target=our_address)) message_handler.on_message(mock_raiden, locked_transfer_for_us) assert_method_call(mock_raiden, "target_mediated_transfer", locked_transfer_for_us) mock_raiden.default_secret_registry.is_secret_registered = lambda **_: True message_handler.on_message(mock_raiden, locked_transfer) assert not mock_raiden.mediate_mediated_transfer.called assert not mock_raiden.target_mediated_transfer.called mock_raiden.default_secret_registry.is_secret_registered = lambda **_: False params = dict( payment_identifier=13, amount=14, expiration=15, secrethash=factories.UNIT_SECRETHASH ) secret_request = SecretRequest( message_identifier=16, signature=factories.EMPTY_SIGNATURE, **params ) secret_request.sign(signer) receive = ReceiveSecretRequest(sender=sender, **params) message_handler.on_message(mock_raiden, secret_request) assert_method_call(mock_raiden, "handle_and_track_state_changes", [receive]) secret = factories.make_secret() reveal_secret = RevealSecret( message_identifier=100, signature=factories.EMPTY_SIGNATURE, secret=secret ) reveal_secret.sign(signer) receive = ReceiveSecretReveal(sender=sender, secret=secret) message_handler.on_message(mock_raiden, reveal_secret) assert_method_call(mock_raiden, "handle_and_track_state_changes", [receive]) properties: factories.UnlockProperties = factories.create_properties( factories.UnlockProperties() ) unlock = factories.create(properties) unlock.sign(signer) balance_proof = factories.make_signed_balance_proof_from_unsigned( factories.create(properties.balance_proof), signer, unlock.message_hash ) receive = ReceiveUnlock( message_identifier=properties.message_identifier, secret=properties.secret, balance_proof=balance_proof, sender=sender, ) message_handler.on_message(mock_raiden, unlock) assert_method_call(mock_raiden, "handle_and_track_state_changes", [receive]) properties: factories.LockExpiredProperties = factories.create_properties( factories.LockExpiredProperties() ) lock_expired = factories.create(properties) lock_expired.sign(signer) balance_proof = factories.make_signed_balance_proof_from_unsigned( factories.create(properties.balance_proof), signer, lock_expired.message_hash ) receive = ReceiveLockExpired( balance_proof=balance_proof, message_identifier=properties.message_identifier, secrethash=properties.secrethash, # pylint: disable=no-member sender=sender, ) message_handler.on_message(mock_raiden, lock_expired) assert_method_call(mock_raiden, "handle_and_track_state_changes", [receive]) delivered = Delivered(delivered_message_identifier=1, signature=factories.EMPTY_SIGNATURE) delivered.sign(signer) receive = ReceiveDelivered(message_identifier=1, sender=sender) message_handler.on_message(mock_raiden, delivered) assert_method_call(mock_raiden, "handle_and_track_state_changes", [receive]) processed = Processed(message_identifier=42, signature=factories.EMPTY_SIGNATURE) processed.sign(signer) receive = ReceiveProcessed(message_identifier=42, sender=sender) message_handler.on_message(mock_raiden, processed) assert_method_call(mock_raiden, "handle_and_track_state_changes", [receive])
def test_encoding_and_decoding(): message_factories = ( factories.LockedTransferProperties(), factories.RefundTransferProperties(), factories.LockExpiredProperties(), factories.UnlockProperties(), ) messages = [factories.create(factory) for factory in message_factories] # TODO Handle these with factories once #5091 is implemented messages.append( Delivered( delivered_message_identifier=factories.make_message_identifier(), signature=factories.make_signature(), )) messages.append( Processed( message_identifier=factories.make_message_identifier(), signature=factories.make_signature(), )) messages.append( RevealSecret( message_identifier=factories.make_message_identifier(), secret=factories.make_secret(), signature=factories.make_signature(), )) messages.append( SecretRequest( message_identifier=factories.make_message_identifier(), payment_identifier=factories.make_payment_id(), secrethash=factories.make_secret_hash(), amount=factories.make_token_amount(), expiration=factories.make_block_number(), signature=factories.make_signature(), )) messages.append( WithdrawRequest( message_identifier=factories.make_message_identifier(), chain_id=factories.make_chain_id(), token_network_address=factories.make_token_network_address(), channel_identifier=factories.make_channel_identifier(), participant=factories.make_address(), total_withdraw=factories.make_token_amount(), nonce=factories.make_nonce(), expiration=factories.make_block_number(), signature=factories.make_signature(), )) messages.append( WithdrawConfirmation( message_identifier=factories.make_message_identifier(), chain_id=factories.make_chain_id(), token_network_address=factories.make_token_network_address(), channel_identifier=factories.make_channel_identifier(), participant=factories.make_address(), total_withdraw=factories.make_token_amount(), nonce=factories.make_nonce(), expiration=factories.make_block_number(), signature=factories.make_signature(), )) messages.append( WithdrawExpired( message_identifier=factories.make_message_identifier(), chain_id=factories.make_chain_id(), token_network_address=factories.make_token_network_address(), channel_identifier=factories.make_channel_identifier(), participant=factories.make_address(), total_withdraw=factories.make_token_amount(), nonce=factories.make_nonce(), expiration=factories.make_block_number(), signature=factories.make_signature(), )) messages.append( PFSCapacityUpdate( canonical_identifier=factories.make_canonical_identifier(), updating_participant=factories.make_address(), other_participant=factories.make_address(), updating_nonce=factories.make_nonce(), other_nonce=factories.make_nonce(), updating_capacity=factories.make_token_amount(), other_capacity=factories.make_token_amount(), reveal_timeout=factories.make_uint64(), signature=factories.make_signature(), )) messages.append( PFSFeeUpdate( canonical_identifier=factories.make_canonical_identifier(), updating_participant=factories.make_address(), fee_schedule=factories.create( factories.FeeScheduleStateProperties()), timestamp=datetime.now(), signature=factories.make_signature(), )) messages.append( RequestMonitoring( reward_amount=factories.make_token_amount(), balance_proof=SignedBlindedBalanceProof. from_balance_proof_signed_state( factories.create( factories.BalanceProofSignedStateProperties())), monitoring_service_contract_address=factories.make_address(), non_closing_participant=factories.make_address(), non_closing_signature=factories.make_signature(), signature=factories.make_signature(), )) for message in messages: serialized = MessageSerializer.serialize(message) deserialized = MessageSerializer.deserialize(serialized) assert deserialized == message
ActionInitMediator, ReceiveLockExpired, ReceiveSecretReveal, ReceiveTransferRefund, ) from raiden.transfer.state import ( NODE_NETWORK_UNREACHABLE, balanceproof_from_envelope, message_identifier_from_prng, ) from raiden.transfer.state_change import Block, ContractReceiveSecretReveal from raiden.utils.signer import LocalSigner LONG_EXPIRATION = factories.create_properties( factories.LockedTransferSignedStateProperties( transfer=factories.LockedTransferProperties(expiration=30), )) def test_payer_enter_danger_zone_with_transfer_payed(): """ A mediator may have paid the next hop (payee), and didn't get paid by the previous hop (payer). When this happens, an assertion must not be hit, because it means the transfer must be unlocked on-chain. Issue: https://github.com/raiden-network/raiden/issues/1013 """ block_number = 5 pseudo_random_generator = random.Random() channels = factories.mediator_make_channel_pair()
def test_mediated_transfer_calls_pfs(raiden_chain: List[App], token_addresses: List[TokenAddress]): app0, app1, app2 = raiden_chain 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, "Fixture token_addresses don't have correspoding token_network" with patch("raiden.routing.query_paths", return_value=([], None)) as patched: app0.raiden.start_mediated_transfer_with_secret( token_network_address=token_network_address, amount=PaymentAmount(10), target=TargetAddress(app1.raiden.address), identifier=PaymentID(1), secret=Secret(b"1" * 32), ) assert not patched.called # Setup PFS config app0.raiden.config.pfs_config = PFSConfig( info=PFSInfo( url="mock-address", chain_id=app0.raiden.rpc_client.chain_id, token_network_registry_address=token_network_registry_address, user_deposit_address=factories.make_address(), payment_address=factories.make_address(), confirmed_block_number=chain_state.block_number, message="", operator="", version="", price=TokenAmount(0), ), maximum_fee=TokenAmount(100), iou_timeout=BlockTimeout(100), max_paths=5, ) app0.raiden.start_mediated_transfer_with_secret( token_network_address=token_network_address, amount=PaymentAmount(11), target=TargetAddress(app2.raiden.address), identifier=PaymentID(2), secret=Secret(b"2" * 32), ) assert patched.call_count == 1 # Mediator should not re-query PFS locked_transfer = factories.create( factories.LockedTransferProperties( amount=TokenAmount(5), initiator=factories.HOP1, target=TargetAddress(app2.raiden.address), sender=factories.HOP1, pkey=factories.HOP1_KEY, token=token_address, canonical_identifier=factories.make_canonical_identifier( token_network_address=token_network_address ), ) ) app0.raiden.on_messages([locked_transfer]) assert patched.call_count == 1
def test_mediator_task_view(): """Same as above for mediator tasks.""" secret1 = factories.make_secret(1) locked_amount1 = 11 payee_transfer = factories.create( factories.LockedTransferProperties(secret=secret1)) payer_transfer = factories.create( factories.LockedTransferSignedStateProperties( transfer=factories.LockedTransferProperties( secret=secret1, payment_identifier=1, balance_proof=factories.BalanceProofProperties( locked_amount=locked_amount1, ), ), )) secrethash1 = payee_transfer.lock.secrethash initiator = payee_transfer.initiator initiator_channel = factories.create( factories.NettingChannelStateProperties( partner_state=factories.NettingChannelEndStateProperties( address=initiator, balance=100), )) routes = [factories.route_from_channel(initiator_channel)] transfer_state1 = MediatorTransferState(secrethash=secrethash1, routes=routes) transfer_state1.transfers_pair.append( MediationPairState( payer_transfer=payer_transfer, payee_transfer=payee_transfer, payee_address=payee_transfer.target, )) task1 = MediatorTask( token_network_identifier=factories.UNIT_TOKEN_NETWORK_ADDRESS, mediator_state=transfer_state1, ) secret2 = factories.make_secret(2) locked_amount2 = 13 transfer2 = factories.create( factories.LockedTransferSignedStateProperties( transfer=factories.LockedTransferProperties( secret=secret2, payment_identifier=2, balance_proof=factories.BalanceProofProperties( locked_amount=locked_amount2, ), ), )) secrethash2 = transfer2.lock.secrethash transfer_state2 = MediatorTransferState(secrethash=secrethash2, routes=routes) transfer_state2.waiting_transfer = WaitingTransferState(transfer=transfer2) task2 = MediatorTask( token_network_identifier=factories.UNIT_TOKEN_NETWORK_ADDRESS, mediator_state=transfer_state2, ) payment_mapping = {secrethash1: task1, secrethash2: 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_can_round_trip_serialize_locked_transfer(): locked_transfer = factories.create( factories.LockedTransferProperties(sender=ADDRESS, pkey=PRIVKEY)) as_dict = DictSerializer.serialize(locked_transfer) assert DictSerializer.deserialize(as_dict) == locked_transfer
def test_regression_mediator_task_no_routes(): """ The mediator must only be cleared after the waiting transfer's lock has been handled. If a node receives a transfer to mediate, but there is no route available (because there is no sufficient capacity or the partner nodes are offline), and a refund is not possible, the mediator task must not be cleared, otherwise followup remove expired lock messages wont be processed and the nodes will get out of sync. """ pseudo_random_generator = random.Random() channels = make_channel_set([ NettingChannelStateProperties( our_state=NettingChannelEndStateProperties(balance=0), partner_state=NettingChannelEndStateProperties( balance=10, address=HOP2, privatekey=HOP2_KEY, ), ), ]) payer_transfer = factories.make_signed_transfer_for( channels[0], factories.LockedTransferSignedStateProperties( sender=HOP2, pkey=HOP2_KEY, transfer=factories.LockedTransferProperties(expiration=30), )) init_state_change = ActionInitMediator( channels.get_routes(), channels.get_route(0), payer_transfer, ) init_iteration = mediator.state_transition( mediator_state=None, state_change=init_state_change, channelidentifiers_to_channels=channels.channel_map, nodeaddresses_to_networkstates=channels.nodeaddresses_to_networkstates, pseudo_random_generator=pseudo_random_generator, block_number=5, block_hash=factories.make_block_hash(), ) msg = 'The task must not be cleared, even if there is no route to forward the transfer' assert init_iteration.new_state is not None, msg assert init_iteration.new_state.waiting_transfer.transfer == payer_transfer assert search_for_item(init_iteration.events, SendLockedTransfer, {}) is None assert search_for_item(init_iteration.events, SendRefundTransfer, {}) is None secrethash = UNIT_SECRETHASH lock = channels[0].partner_state.secrethashes_to_lockedlocks[secrethash] # Creates a transfer as it was from the *partner* send_lock_expired, _ = channel.create_sendexpiredlock( sender_end_state=channels[0].partner_state, locked_lock=lock, pseudo_random_generator=pseudo_random_generator, chain_id=channels[0].chain_id, token_network_identifier=channels[0].token_network_identifier, channel_identifier=channels[0].identifier, recipient=channels[0].our_state.address, ) assert send_lock_expired lock_expired_message = message_from_sendevent(send_lock_expired, HOP1) lock_expired_message.sign(LocalSigner(channels.partner_privatekeys[0])) balance_proof = balanceproof_from_envelope(lock_expired_message) message_identifier = message_identifier_from_prng(pseudo_random_generator) # Regression: The mediator must still be able to process the block which # expires the lock expired_block_number = channel.get_sender_expiration_threshold(lock) block_hash = factories.make_block_hash() expire_block_iteration = mediator.state_transition( mediator_state=init_iteration.new_state, state_change=Block( block_number=expired_block_number, gas_limit=0, block_hash=block_hash, ), channelidentifiers_to_channels=channels.channel_map, nodeaddresses_to_networkstates=channels.nodeaddresses_to_networkstates, pseudo_random_generator=pseudo_random_generator, block_number=expired_block_number, block_hash=block_hash, ) assert expire_block_iteration.new_state is not None receive_expired_iteration = mediator.state_transition( mediator_state=expire_block_iteration.new_state, state_change=ReceiveLockExpired( balance_proof=balance_proof, secrethash=secrethash, message_identifier=message_identifier, ), channelidentifiers_to_channels=channels.channel_map, nodeaddresses_to_networkstates=channels.nodeaddresses_to_networkstates, pseudo_random_generator=pseudo_random_generator, block_number=expired_block_number, block_hash=block_hash, ) msg = 'The only used channel had the lock cleared, the task must be cleared' assert receive_expired_iteration.new_state is None, msg assert secrethash not in channels[ 0].partner_state.secrethashes_to_lockedlocks
from raiden.messages.synchronization import Delivered, Processed from raiden.messages.transfers import RevealSecret, SecretRequest from raiden.messages.withdraw import WithdrawConfirmation, WithdrawExpired, WithdrawRequest from raiden.storage.serialization import JSONSerializer from raiden.storage.serialization.serializer import MessageSerializer from raiden.tests.utils import factories from raiden.transfer import state, state_change from raiden.utils.signer import LocalSigner # Required for test_message_identical. It would be better to have a set of # messages that don't depend on randomness for that test. But right now, we # don't have that. random.seed(1) message_factories = ( factories.LockedTransferProperties(), factories.RefundTransferProperties(), factories.LockExpiredProperties(), factories.UnlockProperties(), ) messages = [factories.create(factory) for factory in message_factories] # TODO Handle these with factories once #5091 is implemented messages.append( Delivered( delivered_message_identifier=factories.make_message_identifier(), signature=factories.make_signature(), ) ) messages.append( Processed(